Index: tags/1.2.7/AUTHORS =================================================================== --- tags/1.2.7/AUTHORS (nonexistent) +++ tags/1.2.7/AUTHORS (revision 13657) @@ -0,0 +1,13 @@ +pcb-rnd maintainer: Tibor 'Igor2' Palinkas +email: pcb-rnd (at) igor2.repo.hu +Chat, IRC: http://repo.hu/projects/pcb-rnd/irc.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/1.2.7/COPYING =================================================================== --- tags/1.2.7/COPYING (nonexistent) +++ tags/1.2.7/COPYING (revision 13657) @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General +Public License instead of this License. Index: tags/1.2.7/Changelog =================================================================== --- tags/1.2.7/Changelog (nonexistent) +++ tags/1.2.7/Changelog (revision 13657) @@ -0,0 +1,2083 @@ +pcb-rnd 1.2.7 (r13656) +~~~~~~~~~~~~~~~~~~~~~~ + [padstack] + -Add: pad stacks: generic object for pins, pads , vias and holes + + [core] + -Fix: when a new file is created by a save and there's no format preference of the board, the "by file name extension" heuristics should pick the matching plugin with the highest save_preference_prio value instead of picking the first available (fixes the bug that new boards were saved as lihata v1 instead of lihata v4) + -Fix: conf: mkdir ~/.pcb-rnd if does not exist so user config can be saved on request + -Fix: Display(ToggleGrid) action now sets the grid relative to the crosshair, not the mouse cursor position + -Fix: Draw buffer lines/arcs as outline instead of thin-draw. Solves problem with zero length lines + -Fix: Draw pin/pad labels on top of other layers + -Fix: ElementList(): get original-element rotation, offset and side uniformly, both for elem and subc + -Fix: Far-side composite silk was being drawn in front-side colour + -Fix: SetValue() text scale change with the wrong increment + -Fix: buffer is not bound to a board, not even after a board is loaded into the buffer; buffers should be board-neutral + -Fix: buffer paste layer binding bug: if the buffer has no layers only globals, don't bother copying layer objects + -Fix: check if layer is not null (fixes polygon undo bug) + -Fix: data model bug: when deleting an object, it is copied to the list of removed objects; do not clear the parent field after the deletion, but leave it to point to the data of that list + -Fix: don't clamp arc angles between 0 and +360 but -360 and +360 - this lets the user explicitly set start angle or delta angle to -90 + -Fix: don't select locked objects + -Fix: draw padstack holes after padstack shapes (some exporters, like ps, depends on overwriting pixels with holes so holes need to be drawn last) + -Fix: import board to buffer layer mixup: the code shall convert all imported layers to dangling bound layers first, then do the binding to the current board + -Fix: memory leak: buffer uninit: don't do layer binding right before all data is free'd + -Fix: memory leak: default layer names in pcb_data_t destroy + -Fix: memory leak: design path and real file name of the board to be loaded in case the load fails + -Fix: memory leak: hid color cache destroy should free the names allocated by the lib + -Fix: memory leak: on footprint plugin root path + -Fix: memory leak: on plugin dir builds + -Fix: pcb_loop_layers() doesn't depend on global PCB + -Fix: pin/via in box macro: true only if the whole pin/via is in, ring incldued, not if the center is in + -Fix: quoted-string printf handles empty string properly + -Fix: remove buggy optimization: do not rotate the bounding box on 90 deg rotation, but recalculate - because of our open/closed boxes, rotation breaks the optimization + -Fix: remove dangerous pcb_get_num() from the API + -Fix: rounding error: repeated 't' and 'T' text value changes won't get the text scale drifting by a few percent + -Fix: selection box bug: semi-negative selection failed on lines and arcs + -Fix: text draw doesn't blindly trust that the layer is a real layer + -Fix: when drawing an object preview, temporary switch off flips + -Fix: when drawing objects on bound layers (e.g. a subcircuit for a preview window), use a more advanced color logics: objects on top copper and silk layer should have board colors, the rest should have far-side color + -Fix: when importing a board into the paste buffer, do not add the current board's layer stack on the buffer before the load - let the loaded board decide about its layers + -Fix: when picking the color for drawing an object on a bound layer, pick the real color right from the config, not the layer's color - layer's color is 'infected' by side flips + -Change: rewrite pcb_select_block() with rtrees so it can consider floaters + -Cleanup: API in headers shall contain parameter names; remove useless doxygen comments and add shorter, but more useful plain C comments + -Cleanup: disperse objects call doesn't rely on PCB + -Cleanup: remove PCB-> references from data.[ch]] and from layer rename + -Cleanup: remove code duplication in layer rename low and hight level + -Del: get rid of vtptr in favor of stock genvector vtp0 + -Del: retire free_atexit() - rather depend on uninit functions + -Update: Enable cycledrag in rubberband mode + -Add: API for properly destroying a HID color cache (to let exporters plug memory leaks) + -Add: Backup() action to force a backup - useful for testing dangerous actions + -Add: HID config option for enforcing composite draw - requred by png photo mode + -Add: Reset the rubberband before looking-up new rubber lines when cycle-dragging + -Add: Support for rubberband when moving arc points + -Add: crosshair snap: polygon center if the polygon is a terminal and the center point is within the polygon (center as in: bounding box center) + -Add: data helper function that lists terminals within data + -Add: data mirror optionally mirrors text (by sending text on the other side) + -Add: disperse elements now works on subcircuits as well + -Add: extend the menu key handling API to receive both the raw base key and the translated key character from the HID + -Add: extend the wireframe line draw API so that it has an argument for square cap lines + -Add: free-rotate-at-cursor call + -Add: function to list objects by type and mask into a pointer vector + -Add: generic, flat data iterator on the children of pcb_data_t + -Add: import subc, not only element, when replacing existing elements + -Add: loop_all and obj_any should include subc + -Add: noclip version of the move operation on the basic object types + -Add: operation for pure clipping (clearing or restoring poly) of the basic objects + -Add: pass a flag to search-by-location to handle floaters; search code can pick floaters over subc + -Add: pcb_data_bbox() can ignore floaters + -Add: portable fileno() wrapper + -Add: portable milisecond sleep API + -Add: standard operation: free rotate (on all existing object types of the new model) + -Add: text "flip side" is really a latent mirror - give it the usual y_offs so it works properly in subc mirroring + -Add: when moving floaters, draw a xor-line back to the origin of the parent subc (emulates moving name of an element) + -Add: optional per object color override + + [layer] + -Fix: wrong pcb printf args on layer edit attributes window title build + -Fix: when setting up all-layer bindings to a board, do only as many layers as the board really has and remember this number in new data + -Fix: layer type lookup shouldn't crash on UI layers + -Cleanup: remove global var PCB dependency + -Cleanup: remove redundant bound/real .name fields, use a common .name field - both have names and the two fields used to be one the same address anyway + -Cleanup: move grp to under meta.real - bound layers are not in groups + -Del: old macro to determine if a layer is bound, using indirect data - depend on direct data + -Add: copper layer group list cache for fast bbvia lookup + -Add: central layer stack free function + -Add: function to convert all layers of a pcb_data_t * to dangling bound layers using a reference layer stack + + [subc] + -Fix: LoadFootprint() accepts subc as a footprint + -Fix: always display the refdes in the top-left corner of the dashed subc outline, even if the view is flipped + -Fix: crosshair object snap: subc origin should be snapped to + -Fix: don't draw at every subc op, that slows down rat find + -Fix: dup(): copy subc metadata (e.g. attributes) before copying layer data; some layer data, like text bounding box, does depend on this metadata + -Fix: include the name of the layer in the error message when a subc layer can not be bound + -Fix: instead of direct move, use 3 stage move: restore polys, move, clear polys (fixes Ade's and JG's bugreport about small smd resistor clipping bug) + -Fix: keep track of whether a buffer is loaded from the outside or is from the board; when loaded from the outside, subc pasting is affected by current side, else side is kept (this fixes a decade old bg about element having to be put on solder or component side on the moment of load, not on the moment of paste) + -Fix: poerply dup the name of layers on creating new subc layers when converting from buffer + -Fix: subc load to buffer: list type correctness (subc list instead of element list) + -Fix: swap side needs to modify the subc pointer (creating a new subc) + -Fix: terminal rendering: use pixel based terminal layer mark size + -Fix: update dyntext texts when parent subc attribute changes so that the new bbox is calculated + -Fix: when a subc/term poly is copied, it should create its clearance + -Fix: when find.c removes flags, it should recurse to subcircuits as subcircuits parts may be found too + -Fix: when placing a subc on the solder side, the other-side part of the operation shall not be undoable, it's just part of the placement + -Add: DRC silk min width considers arc + -Add: Flip() on selected objects includes subcircuits + -Add: action ElementList() can replace element to subc + -Add: call to determine if a subc is on top or on bottom, using the aux layer + -Add: call to send all selected subcircuits to the back side + -Add: free rotate operation + -Add: free rotate subc when rotating a buffer + -Add: helper function for 90 deg subc rotation + -Add: high level move() call + -Add: implement DRC minimal silk width check for subcircuits + -Add: implement nonetlist flag set (alt+n) + -Add: implement undoable subc removal + -Add: minimal silk width DRC violation: also select the offending lines + -Add: prepare ElementList(), ElementSetAttr(), ElementList() for subcs + -Add: preview draw function + -Add: properly draw the xor-outline of the subc while visualising the buffer, even on the bottom side + -Add: search subc by ID + -Add: support for loose subc (in-place editing, ignoring the 'subc lock' for subc parts) + -Add: the floater flag (and concept); buffer->subc conversion creates refdes text as a floater + -Add: when loading a footprint as board (footprint editing), enable loose subc + + [term] + -Fix: poly-poly clearance: consider all layers in the same (real) layer group + -Fix: delayed label draw: do not draw layer object terminal ID on board if it's on the other side (mimicks the old pad behavior) + -Fix: reset delayed label draw array after each succesful batch draw + + [thermal] + -Add: poly thermal calculations + -Add: line thermal calculations + -Add: arc thermal calculations + -Add: padstack thermal calculations + + [tool] + -Split: tool implementtion from random parts of the code regrouped into per tool files + -Add: function callback API for tools + + [doc] + -Change: cut ties with gEDA + -Add: minimal description of subcircuits in data model + -Add: document padstacks and bbvia in data model + -Update: current list of keys + -Add: a note about explicit refresh in fp_wget + -Add: document what's new in lihata v4 + -Add: explicit history section for 2016 and 2017 + + [autocrop] + -Add: move padstacks too + -Add: move subcircuits + + [autoplace] + -Add: handle subc and padstack and layer object terminals on connection mapping + + [brave] + -Add: brave mode for testing new feautres (with dialog box) + -Add: brave mode for "use padstack instead of via" + + [draw_csect] + -Add: editable outline layer group + + [dsn] + -Add: export subcircuits as parts (without terminals) + + [export_dsn] + -Fix: missing layer name quoting + -Fix: don't use g_free() on normal strdup()'d padstack strings + -Add: export polygon based heavy terminals of subcs + -Add: export subc pins + + [export_png] + -Fix: photo mode mask broke because of lack of proper compositing; add basic compositing draw + -Fix: force compositing draw in photo mode, as photo mode will try to combine the output layergroup by layergroup and non-compositing may merge multiple groups in a single session + -Fix: properly draw darkish shadow for all internal/other-side copper layers in photo mode + -Fix: always do the fr4 color bending, not only on 2 layer boards + -Fix: free erase and im after finishing the export so that a new export won't inherit a potentially smaller image buffer; this fixes 'mask drawn too small' + -Fix: memory leak - free all the large image buffers after finishing the export + -Fix: memory leak on colors and brushes + -Tune: photo mode mask shadow color + + [export_ps] + -Fix: --ps-color got in a never-running part of the code after the composite layer rewrite + -Fix: drawing drill holes + -Fix: overflow in media size + + [export_svg] + -Fix: implement missing fill_poly_offs - required for exporting padstacks + + [extedit] + -Add: new plugin for external edit of subcircuits + + [fp_fs] + -Fix: silently ignore .lht and .subc.lht suffix when matching unsuffixed footprint names so subcircuits are found + + [fp_wget] + -Fix: broken string end comparison + -Fix: if wget fails, remove the partial/empty download so thet cache doesn't get fooled by the file date + + [gtk] + -Fix: use the proper function to destroy the command dialog. + -Fix: proper toggling of plugins/hid_gtk/use_command_window conf. setting + -Fix: display/hide the embedded command combo box, in fullscreen too. + -Fix: proper management of timer avoids a GLib-CRITICAL + -Fix: property editor preview: memcpy from the wrong layer stack + -Fix: text scale change should get the status line redrawn + -Fix: partial fix for non-US keyboard issue; introduce in the menu files + -Cleanup: use a generic status line update instead of many copies of the same function + -Change: do not thin silk lines and arcs for element preview: this feature won't be available for subcircuits + -Change: don't set termname on pins and pads when making the preview dialog so that later the copy can be avoided + -Change: "element" preview upgraded to generic object preview so that it can display subcircuits too + -Change: Full Screen button is now a smaller icon button. + -Add: implement the attribute dialog widget hide/unhide API + -Add: DAD set() can set the label on a button + -Add: attempt to explain window geometry save error (after failing on a missing project or read-only user config) + + [hid] + -Fix: in gtk, the only safe way to unwatch a file from a watch callback is using the return value; upgrade the HID API to support this usage of the callback return value; fixes subsequent calls of extedit + -Cleanup: remove PCB_HATT_MIXED: we have PCB_HATT_COORD for the common case instead, and the uncommon case should be solved using a HBOX + -Add: When drawing lines, treat negative width as pixels instead of world coordinates (marks/labels can be drawn in pixel widths) + -Add: DAD boxed and tables are scrolled when the scroll flag is set + -Add: new API for drawing a filled polygon with offset + -Add: DAD interface for coord edit + -Add: api for hiding/unhiding widgets on an attribute dialog + -Add: DAD support for REAL fields + -Add: DAD support for uninitialized dlg (to be used in structs, for non-modal support) + -Add: attr dialog API adds a new argument for dialogs being modal (so that non-modal DAD dialogs are possible) + -Add: event callback in the 3-stage DAD API; attribute dialog button event for window close + + [hid_gtk2_gl] + -Fix: Zero length square capped lines were not drawn + -Fix: GL HID was drawing far-side silk on top + -Add: Draw local grid in GL hid + + [import_*] + -Fix: cancel on import doesn't mean syntax error + + [import_hpgl] + -Fix: use only as many layers as many pens are in use in the file; name the layers by pen number + + [import_sch] + -Fix: proper subst in schematics path + + [io_eagle] + -Fix: correctly parsing larger SMD pad dimensions. + -Fix: Rectangle parsing now uses design rule ms_width, reduced code duplication + -Fix: parse signal, element, symbol etc name fields as string, not Int + -Fix: arc parsing for linetype 127 + -Fix: drill and diameter doubled as required for through hole pads/pins + -Fix: netlist node names default to pin number if no name string found. + -Fix: pathological arcs in binary format with start + delta + -Fix: text on layer 51 now created on 21, and invalid element names '-' changed to 'HYPHEN' to fix netlist parsing + -Fix: element name substitution if element name is '-' change to 'HYPHEN' + -Add: post-processing to fix nested 'signal' nodes; smilie's missing wires are now being parsed. + -Add: eagle binary netlist parsing/loading of 'element_name-pin_number' for given net + -Add: using binary design rules values for mdWireWire, msWidth, rvPadTop, rvPadInner, rvPadBottom + -Add: further clarification of requirements for lib/pkg pin/pad "name" retrieval for nets + -Add: reinstate rendering of arcs on tDocu layers within elements, tested in v3 binary + -Add: layers 51 (tDocu) and 52 (bDocu) supported as layers in top and bottom silk groups + -Add: support for Eagle binary and XML library files (.lbr) + -Add: read.c adds description, element given in library file, and NAME, VALUE to footprint generated + -Add: support for loading dru parsing + + [io_kicad] + -Fix: correct handling of (at X Y rot) rotation value for footprint padsw! in layouts + -Add: support for title_block, and fixed premature module parse termination with unsupported fp_line layers + + [io_lihata] + -Fix: when loading a subc, ignore floaters in bbox calculation + -Fix: parse element does the same footprint search procedure as io_pcb does + -Fix: don't attempt to close the footprint file when open failed + -Fix: when loading polygon points, set X2 and Y2 to 0 to keep compatibility with the poly code assumptions - fixes random-jumping poly corners + -Fix: respect the version the user request for saving a subc in, but bump it (and warn) if there are padstacks in the subc + -Fix: when loading subc from file, parse the version separately and accept anything from v3 up + -Fix: when loading subc as a board, make sure all polygons are clipped + -Fix: memory leak: free error message string after load + -Fix: memory leak: free() polygon point table cells before overwriting them + -Fix: memory leak: macro parameter evaluation side effect caused multiple copies of whole subc subtrees never getting in the final document tree + -Del: remove the hackish PCB swap - now that the layer code is PCB-safe + -Add: lihata format v4, support for padstacks + + [lesstif] + -Fix: Tool ghost is shown, now. + -Add: DAD: implement the attribute dialog widget hide/unhide API, make sure hbox/vbox/table widgets are stored + -Add: DAD: set() can set the label on a button + -Add: DAD: support for non-modal attribute dialogs + -Add: DAD: ok/cancel button callbacks on attribute dialogs + + [mincut] + -Workaround: broken find.c returns rat point as rat line + -Add: show a progress bar after 1+ second of mincut hunting; cancel should revert to dumb indication + + [polygon] + -Fix: poly-poly clear and restore shall not run on polygons that are not part of a board (e.g. buffer polys) + -Fix: bounding box calculation allows negative coordinates + -Fix: recalculate bounding box after 90 deg rotation - simply rotating the box won't work because the box is 'closed' (increased by 1 on the bottom and right) + -Fix: coord size assumptions + -Fix: poly-poly clear: always execute ppclear and pprestore on a board layer + -Fix: poly-clear-poly: if two clearing polys collide, the code shouldn't return error, that'd cause other, legit clearances to be omitted (there's no real poly z order) + -Fix: undo/redo clearance asserts: high level poly code should not attempt to clear/restore polygons on pcb_data_t that is not the data of a board + -Add: low level function to calculate whether a line interstects with a pline + -Add: low level functions to efficiently determine whether a circle is within a polyline or corssing a polyline (or out of the polyline) + -Add: helper functions to peek into the vectors for previous/next contour point without bumping the iterator + -Add: inline helper function for setting up a polygon iterator on a polyarea + -Add: low level polyarea move function + + [report] + -Add: report unclipped poly area (using currently active unit) + -Add: search padstacks for holes + + [rubberband_orig] + -Fix: Rubberband lines with pins/pads didn't always work or could crash due to uninitialised variable + -Fix: Don't create more than one rubberband object per line when checking polygon connections. + -Add: Rubberband support for subc polygons + -Add: Rubberband support for subc line terminals + -Add: Rubberband support for subc arc terminals + + [scconfig] + -Fix: unportected "." in regex made tool_lock.c look like a _l.c generating broken C compilation rules + -Fix: libminuid should be compiled with the CFLAGS and LDFLAGS detected + -Fix: map_plugins.sh warns for invalid default + -Fix: map_plugins should sort deps for reproducible output + -Fix: instead of guessing where to include opengl from, rely on the include prefix detected by scconfig + -Add: define PCB_INLINE to simplify the code for static inline functions + -Add: proper detection of fileno() - it's _fileno() on windows + -Add: detect GLU if hid_gtk2_gl is to be compiled + -Add: detect GLU and generate opengl.h accordingly + + [select] + -Fix: missing case for box-near-check for element-text (made unselecting refdes hard) + + [shape] + -Add: shape generator, with dialog box support + + [smartdisperse] + -Fix: don't cast coord to long - coord may be wider + -Add: handle subcircuits + -Add: mark non-selected-visited should work on subc as well + + [undo] + -Fix: a totally empty undo buffer is not an error, not even if serial==0 in this case + -Fix: pcb_undo return value was not consistent, now it returns -1 on error and 0 on success + + [util] + -Fix: keylist cleans up strings in the key column so "/" is properly displayed + -Update: teach keylist to recognize in key bindings + -Update: gsch2pcb-rnd help text to reflect the new way the import works + -Add: install fp2subc + +pcb-rnd 1.2.6 (r11992) +~~~~~~~~~~~~~~~~~~~~~~ + [core] + -API CHANGE: the attribute system requires unique keys per attribte list; this will keep things concistent as the code used to silently ignore redundant attributes + -Fix: don't merge lines (when drawing extension of an existing line) if their clearance differs + -Fix: pcb-printf: %mk really prints decimil and not some random "sane" unit + -Fix: Mode(escape) should undo Note as well, so if the mouse button is still pressed there won't be a selection box after the release + -Fix: select polygon only if the negative selection box really touches it + -Fix: function pcb_is_arc_in_rectangle besides crossing, now checks if a whole arc is inside a rectangle + -Fix: select arc only if the negative selection box really touches it + -Fix: remove duplicate lists of "what flags this object type can have" - rather have a function that calculates it from the flag_str table and cache it + -Fix: data bbox shouldn't improvize per object type but should depend on each object's bbox calculation function + -Fix: don't change the ID when text is put on a layer - instead, invent the ID when the text is created (to prevent unintentional ID changes, e.g. on lihata load) + -Fix: rotate line point relative to the passed rotation axis, not the line endpoint (fixes undo rotate bug) + -Move: flag help text from doxygen comments to the struct so the code can use them + -Add: attribute post value changed callback + -Add: copy-back API in attrib that minimizes changes (helper for HIDs) + -Add: new interpretation of clearance=0: same as if the clearline flag is not set + -Add: Wireframe draw mode + -Add: marker snap depends on config + -Add: normalize() action for normalizing (clipping and moving into drawing area) data or the board + -Add: pcb_subst_strdup() option for interpreting backslash sequences + -Add: flagedit (accessible from the menu) + + [data] + -Change: switch over from old default.pcb and implicit mask/paste layers to new, lihata based 2 and 4 layer defaults + -Update: names in the desktop file, to pcb-rnd + + [dbus] + -Del: retire this old, unused plugin + + [diag] + -Add: integrity check: attribute list length + -Add: formatted flag dump with new action dumpflag() + + [dialogs] + -Add: new plugin for moving dialog boxes to + -Add: flagedit dialog + -Add: layer bindings dialog + + [doc] + -Add: new composite render API documentation + -Add: explain paste buffers + -Add: refine indent recommendations + -Add: alien format description: Koen's documentation on the hyp format + -Add: minimal openscad documentation and an example model (for 1206) + -Add: vendordrill plugin documentation + -Add: document distalign + -Add: document autocrop + + [draw_fontsel] + -Add: replace font button + + [export_dxf] + -Del: retire the old dxf code - will be rewritten from scratch + -Add: new, lht based template for the base dxf as saved from librecad + + [export_png] + -Change: switch over to the new composite HID API + + [export_ps] + -Change: switch over ps output to the new composite API + -Change: switch over eps to the new drawing mode API - eps is incompatible with composite layers (lack of features in the postscript language) + -Fix: typo made composite layers empty + -Fix: proper max val for calib - let x and y calib take values between 0 and 2 + -Fix: don't omit drill rings when drill helper is on + -Fix: when drawing outline on a drill layer (forced by user option), turn off global.is_drill temporarily to get the right colors + + [export_svg] + -Change: switch over to the new draw mode HID API + -Fix: svg_rect() draws clipping properly + -Add: disable photo mode for composite (they are incompatible) + + [font] + -Add: be able to replace font in place + -Add: be able to replace the default font, font #0 + + [fp] + -Add: accept footprint library search paths starting with '?' - means errors should be ignored + -Change: default config won't emit error on missing library path ../pcblib and ~/pcblib + + [fp_fs] + -Fix: don't segfault on tag-looking empty constructs (##) in fp-looking files + + [hid] + -API CHANGE: new hid render API with better support for rendering composite layers groups + -API CHANGE: new, Dynamic Attribute Dialog (DAD) API + + [hid_gtk2_gdk] + -Update: Updated the GTK2 GTK HID to use the new HID API + -Fix: preview expose saves/restores the base canvas properly so that preview renders don't mix with the main window's + -Fix: typo: filled poly should make changes on the clip buffer when in composite draw + -Change: replace the mask based composite drawing code with the new composite API + -Cleanup: the pixel/clip naming conventions + -Cleanup: reorder priv struct members to group available canvases and currently active drawing settings + -Workaround: for the flashing subc border caused by xor draw in non-direct mode + + [hid_gtk2_gl] + -Update: Updated the GTK2 GL HID to use the new HID API + -Fix: Respect the fullpoly flag when drawing polygons. Draws all poly parts, not just the largest one when the + -Fix: Poly islands within holes were not being drawn in fullpoly mode. Reordered the rendering operations so that + -Fix: Layer stackup window upside down. The view matrix is now set for each layer group as well as at the + + [hid_lesstif] + -Change: update the mask rendering code for the new composite API + -Fix: make sure lesstif cli arg attributes are registered before arg parsing so that CLI args are accepted + -Fix: save all pixmaps when drawing dialogs (fixes lesstif dialogs crashes) + -Fix: swapped coordinates when panning in dialogs - pan works properly in dialogs even if the board is viewed from the solder side + -Fix: set proper background color for preview dialogs + -Fix: move blit-to-window code from SHOW_LEAVE to SHOW_DRAW (fixes dialog glitches at mouse events) + -Fix: save main_pixmap instead of pixmap (fixes pinout preview dialog) + -Fix: don't let scroll go too far from the board - avoids runtime lesstif warnings + -Add: support for the new attribute dialog features + + [import_hpgl] + -Add: libuhpgl, a mini-lib for parsing HPGL + -Add: plugin to import lines and arcs from HPGL + + [intconn] + -Fix: centralize the element-related so that pin-pad and pad-pin intconn would work too + -Fix: short eval code used the wrong check for nonetlist flag indicating intconn jumpers with pins shorted + -Fix: remove intconn from flags and make it a good old common struct field - for easier access and cleaner data structs; keep file format compatibility with .pcb, and lihata board v1 and v2 + -Fix: do not set ->intconn directly, set the attribute instead and let the attribute post hook set the struct field; this will preserve intconn as an attribute on save + + [io] + -Add: set conf node rc/paths/design to the directory path of the current design; this can be used in paths as substitutions using $() + -Fix: don't crash if the preferred IO plugin doesn't offer saving the footprint + + [io_eagle] + -Fix: eagle layer 20 (dimension) [instead of 199 (contour)] now maps to pcb-rnd outline layer + -Add: reading in round/square/octagon pin/via flags in binary. Padstacks required for long/rounded. + -Add: support for rounded SMD pads. Pads now either square, or round. No roundrects possible yet + + [io_lihata] + -Change: bump the priority of lihata v3 so it's the default save format now + -Fix: dummy node should be created with the name the caller requested, not hardwired "attributes" + -Fix: make sure to parse attributes after flags - attributes may effect flags + -Fix: don't attempt to save attributes of bound layers - they have none + -Fix: load the layer combination flag before doing the layer binding + -Fix: persistent save shouldn't crash if an in-memory text node has NULL value, it should inhibit saving that node instead + -Fix: always save layer's obejcts list, even if empty, so the persister can merge the lists + -Add: be able to load a subc as a footprint for editing + -Add: from version 3 save and load polygon clearance field + -Add: write_element hook in the v3 format - save subcircuits + + [layer] + -Change: default layer group names should contain _ instead of space because group names potentially end up in file names and we don't like space in file name + -Change: default visibility turns off mask and paste layers - they are distractive 99% of the time + -Fix: loading a pcb into the buffer should convert real layers to bound layers - that's the only way a buffer can work + -Fix: update layer color cache on config change + -Fix: single negative silk renders properly + -Fix: don't consider a copper layer empty if it has only via/pin rings on it + -Add: attribute edition of the current layer in the layer popup menu + -Add: menu for buffer layer binding change + + [lib_polyhelp] + -Add: PolyOffs() action that duplicates selected polygons with an offset on their size + -Add: ToPoly() action that converts any group of objects to a polygon + + [mincut] + -Fix: corner case segfault (reported by barjac) + + [openscad] + -Del: retire the original openscad exporter; full rewrite follows + -Add: rewrite from scratch; support board outline, silk, copper, mask and element models + + [poly] + -Add: poly-poly clearance when CLEARPOLYPOLY is set + + [propedit] + -Fix: display clearance as copper-to-copper gap width + -Add: force absoltue numeric value with a # prefix - useful for arc angles, e.g. #-90 means "value -90" instead of "decrease current value by 90" + + [report] + -Fix: use uniform terminology for Clearance and arc width + -Add: subcircuit report + + [tests/rtt] + -Fix: don't fail if convert(1) (and ImageMagick in general) is not installed + -Fix: make clean removes out/*/* + -Fix: when dealing with gerbers, don't ignore the drill (*.cnc) files + -Fix: remove all nelma png files - not going to compare them + -Move: validation helpers into a separate dir to reduce number of files in main dir + -Add: composite silk test input + + [rubberband] + -Update: Lines must be connected exactly by endpoints to other line endpoints to be considered for rubberbanding + -Fix: rubber band keeps middle line dir now snaps to grid, undo works and fixed artifacts when moving line + -Fix: Don't keep middle-line dir if the middle line is parallel to any of the rubber lines + -Fix: keep middle-line dir would access the rubberband lines before it had established that there are at least 2 rubber lines. caused a crash + + [safe_fs] + -Add: safe_fs API for wrapping all file and process access + -Add: privisions for regex based rules to deny access + -Add: API for opening a file with path substitution + -Add: API for searching for a file to open recursively under a directory + -Add: pcb_strdup_subst() can replace leading ~ with the user's HOME + -Add: leading '?' in a search path means optional (don't throw error if doesn't exist) + -Cleanup: unify the support of % and $() replacement in paths + + [scconfig] + -Fix: BadWindow bug of hid_lesstif (force-order -lXm before -lXt) + -Add: link-time error for using strcasecmp directly or bypassing safe_fs + -Add: --force-all to override developer's decision whether a plugin is broken + + [subc] + -Change: subc parent API change: don't return int but the parent subc - same for comparison, but more universally usable for other purposes + -Fix: don't lose layer combining flag when copying subc from buffer to board + -Fix: when loading subc into buffer, properly set up buffer offsets so that subc origin is the same as the buffer's origin + -Fix: flip subc when placing on the bottom side + -Add: subc terminals that interact with netlist + -Add: understand the refdes attribute; print refdes on the subc layer + -Add: gui action for editing attributes of a subc + -Add: teach fp_fs to accept subcircuits as footpritns + -Add: subcircuit build the layer binding dialog + -Add: lock tool works on subc + -Add: a subcircuit file can be open for editing, as a footprit file + -Add: make sure element smash -> convert buffer to subc path preserves as many element features as possible + -Add: poly-vs-poly clearance infra (required for subc terminals) + + [tests] + -Update: conftest for the new conf_update API + + [text] + -Add: new text flag: dynamic string in text (to permit % substitution) + -Add: %a.parent.*% parent attribute subsitution + + [undo] + -Cleanup: move undo action related call prototypes in a separate header to match the separate .c + -Clenaup: move out slot field free code from the slot allocation code (slot allocation will be genealized) + -Del: remove local undo list implementation, switch over to libuundo + -Add: dynamic, variable size payload on allocation + + [util] + -Add: bisect helper script + -Add: menu2svg: draw the menu system using graphviz + -Add: fp2subc: convert footprint from the old pcb format to subcircuit + + [vendordrill] + -Fix: missing else made the loader think /drillmap is not a list + -Fix: broken printout units; use %ml for mil instead of manual conversion + -Fix: replace all %f with %ml for coordinate prints + + +pcb-rnd 1.2.5b (r10635+bakcports) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + - Fix: import pcb into paste buffer layer binding bug + - Fix: gerber drill file units + - Fix: RTT tests shouldn't fail if ImageMagick is not installed + - Fix: execution bug fix (do not let action scripts load from board files) + +pcb-rnd 1.2.4 (r10635) +~~~~~~~~~~~~~~~~~~~~~~ + [subc] + -Fix: saving buffer elements shouldn't ever save layer data; introduce an explicit flag for indicating the element-only intention to the io_ plugins so they don't have to guess from buffer layer names + -Fix: poly plow: don't attempt to plow thermal if we are not on a board (but in a buffer - because of dynamic layer bindings) + -Fix: find.c lookup code works in line->poly, arc->poly and poly->poly directions + -Fix: autoroute should look at the rtree, not at the lists, to determine (recursively) if a layer is empty + -Fix: bboard uses rtree instead of list for determining if a layer is to be exported, because of subc + -Fix: don't check buffer validity in core before save, but check it in each io plugin because validity depends on the format + -Fix: RemoveList of undo shouldn't set data->parent to PCB, as it is really independent of the PCB + -Add: subcircuit object + -Add: data model: consistent implementation of parent object, for all existing data + -Add: integrity() checks for global object direct parents (via, element) + -Add: pcb_text_dup() for pasting subcircuit text + -Add: pcb_poly_dup() so that subcircuit paste can copy polygons + -Add: poly dup_at() + -Add: dup_at() for atomic objects + -Add: missing Rotate90 operation for polygons - required for canonical operations on subc + -Add: dup() functions for vias + -Split: move text's XORDraw out from crosshair.c so that it can be reused in subc drawing + -Update: menu files: save buffer is elements or subcircuits; load element/subcircuit in file/import + + [core] + -Fix: break up buffer elements used the same copper layer for both top and bottom pads (bisecting thanks to: miloh) + -Fix: limit thermal flag value to the supported range + -Fix: don't run export on an empty board: it's probably an user mistake and some of the exporters would crash anyway (reported by miloh) + -Fix: line mirror should update bbox and rtree + -Fix: pinvia mirror should update rtree and bbox + -Fix: arc, line, pinvia and poly mirror won't segfault if rtree is NULL (typical for buffer) + -Fix: remaining rats or finishing the rats is no warning, but info + -Fix: pcb_trace() should use pcb_printf() for the pcb-specific types + -Fix: preserve attributes on line/arc/text/poly dup/copy/move + -Fix: when split a line/arc because of insert point, copy metadata from the old line segment to the new + -Fix: don't lose via name, number and attributes on copy/move + -Fix: find-by-obj shouldn't ignore pads + -Fix: Arc intersection bug + -Fix: arc polygon clearance bug: arc conversion to polygon broke if radius was smaller than clearance (resulted in broken end cap and self intersection); implement a more expensive but safe way to construct it from three objects - such small arcs are rare anyway + -Fix: Moving cursor with keyboard allows now leaving snapped pin/pad + -Fix: actions don't rely on implicit XY coords, run the GetXY() (explicit query for coords); makes a difference when called from many + -Fix: draw pins'/pads' names above the silk layer + -Fix: toggleview() shouldn't crash on no-arg + -Fix: when converting a value with unit to coord, clamp the result to COORD_MAX (instead of overflow) + -Fix: mirrored pins/pads numbers after board flip + -Fix: clearance for odd shapes on square+octagon + -Fix: polygon arc clearance drawing rounding error: make sure the last point of the outer arc approximation is drawn; also make sure end cap starts exactly where contour ends + -Fix: proper rounding in arc endpoing calculation + -Fix: text line rounding error + -Add: PasteBuffer() action for moving selection instead of a copy&erase combo (it should keep the ID) + -Add: pcb-printf: %mq support (generic, configurable quoted strings) + -Add: rtree iterator + -Add: y_offs option to all low level mirror functions + -Add: low level pcb_data_t move function + -Add: pcb_data_t normalizer (to fix up board-too-small and negative coords) + -Add: DumpPluginDirs() action and --dump-plugindirs command line switch to ease debugging + -Add: central UTC date print for the export strftime %c unification + -Add: pin/via and pad hashing functions geared for padstacks (ignore coords and names) + -Add: help function to make a net connection list starting from an arbitrary object + -Add: poly contour coord map function that iterates over all islands and holes + -Add: polygon contour loop helpers + -Add: helper function to determine if a pline is rectangle or not + -Add: configurable backup format + -Add: close polygon hole by double click + -Cleanup: arc, line, element, pad, pinvia, poly, rat, subc, text op function names unified + + [layer] + -Fix: don't segfault on resolving a bound layer ID without binding, rather assert + -Fix: compositing: the function that decides whether a group is compositing should only care about negative composites + -Fix: fake composite draw: optimization that temporarily fixes the composite silk and paste missing select color bug for the most common cases + -Fix: do the fake composite layer draw hack optimization only for renderers that explicitly enable it because it interferes with translucency (useful mostly for sw rendering) + -Fix: layer group vs. layer confusion made pad->ratline jump in find.c impossible + -Add: function to calculate the distance between two groups on the stack + -Add: function to count layer groups of a given type stepping through the layer stack in a given direction + -Add: when abstracting an intern copper layer, calculate the copper layer offset + -Cleanup: rename to pcb_layergrp_* for type naming unification + + [build] + -Update: move genht out of liblihata to get a flat project structure + + [lib_polyhelp] + -Add: function to trace a poly contour, from within the poly, with lines + -Add: function to print a pline as an animator script + -Add: horizontal and vertical hatching + -Add: generic poly contour/hatch action: PolyHatch() + + [diag] + -Add: auto-integrity checks when enabled + -Add: check the undo stack integrity as part of the global checks + + [boardflip] + -Fix: make the on-solder toggle flag universal that affects not only elements but text (for mirroring) + + [dbus] + -Change: mark the plugin deprecated + + [draw_fab] + -Fix: drill size units depend on the units setting in gui + + [report] + -Fix: broken tabs + + [export_xy] + -Add: template based output formats + -Add: templates for gxyrs, TM220A p&p, macrofab, KiCad .pos + -Fix: use the central UTC print function instead of strftime %c + -Fix: cookie should not be bom's + + [export_ps] + -Fix: attribute leak on uninit + -Fix: arc corner case: don't div with zero if width is 0 + -Fix: r=0 arc is a point + -Fix: don't use %g for potentially large values, it will break the ps syntax with exponents + + [export_svg] + -Fix: attribute leak on uninit + -Fix: detect ellipitcal arcs and refuse to draw them + -Fix: warn for elliptical arcs only once per gc (which is similar to once per export) to avoid flood of error messages + -Fix: arc endpoint rounding bug; it is more portable and more reproducible to use pcb_round() + + [export_*, import_*] + -Fix: use the central utc print function instead of strftime %c + -Fix: import_tinycad memleak: free argc, argv after use by qparse + -Fix: export_gerber: use pcb_author() instead of getting the user name directly to allow config override (all other exporters do this) + -Fix: export_nelma: attribute leak on uninit + -Fix: export_openscad: rounding errors + -Fix: export_png: attribute leak on uninit + -Add: config setting for default save fp format + -Add: io_hyp: write .hyp files + + [io_eagle] + -Fix: bottom side element rotation. + -Fix: improved n*90 arc type parsing. non n*90 arcs still need work. + -Fix: pad dimensions now being parsed + -Add: infrastructure for abstracting the low level tree (xml vs. binary formats) + -Add: parse the binary format + -Add: "du" decimicron unit to unit.c and unit.h for eagle bin format + + [io_autotrax] + - Add: read Protel autotrax/easytrax board files + - Add: write Protel autotrax/easytrax board files + + [io_kicad] + -Fix: ignore objects on unknown or unsupported layers with a bold warning, instead of returnning an error + -Add: support for bleeding edge kicad 20170123 and (dimension ...) item on layouts + -Add: infra for proper error reporting + -Add: save: (descr "description") field to s-expression modules + -Add: properly quote strings on save + -Add: call the board normalizer after load because kicad accepts negative coords and we don't + -Add: workaround for auto-creating In*.Cu layers - kicad seems to do the same + + [io_lihata] + -Fix: when a .pcb backup file would be saved as .lht.lht.pcb, simplify it to .lht.pcb + -Fix: starting from v2, save data's number-of-layers, not PCB's - subcircuits typically have less layers + -Fix: reset fontkit and default font in parse_fontkit + -Fix: remove backup save in .pcb as it has side effects that might change the board _before_ the lht save + -Add: format version v3: subcircuits + + [io_pcb] + -Fix: accept whitespace in read-check between pcb and bracket, element and bracket (so valid files are not refused) + -Fix: make sure there's a top copper layer and a bottom copper layer when loading an .fp file directly + -Fix: creating top and bottom copper should look up the layer group even in non-debug builds + -Fix: free default font memory properly when parsing font from file + -Fix: font reset mechanism for loading the (optional) font from a .pcb file and for loading a font from a font file; fixes double font load when the default font is changed + + [draw_csect] + -Fix: never draw 0 thick lines, round them up to 1 nm; some exporters hate 0 thickness + + [font] + -Fix: when moving a text without selection, draw the real outline, not the bounding box outline + -Fix: generate the font change event after reading the new font, not before, so that the bounding boxes are calculated properly + -Fix: generate the font change event with the right font ID + -Fix: pcb_font_free() should free polygons and arcs of glyphs and clean the list items for reuse + -Fix: don't overwrite valid loaded fonts' ID and don't free them after loading + -Add: XORDrawText() draws the real outline of the text, not the bounding box + + [tests] + -Fix: build error in uniq_name (genht moved) + -Fix: orig: separate XY and bom testing; the plugin got split long ago + -Fix: orig: uniq name for xy tests + -Fix: orig: rename gerber3 reference layer file names to match the current stackup + -Fix: orig: don't test bottom layer on gerber3: it's empty + -Fix: conf and propedit test build: genht relocation + -Del: don't set the fab user with a non-standard flag + -Add: cli tester for pcb-printf %mq + -Add: enable RTT by default + + [tests/RTT] + -Fix: don't consider "can't export empty design" an error + -Fix: reset search path for default.pcb so the embedded version is used even if there are others installed (to guarantee persistent IDs) + -Fix: use compare(1) for bboard png comparison - different libpngs will result in different binary files + -Fix: use explicit TEST author for testing the text drawn on some output + -Fix: all-input/all-format test fails at the end if any test fails (but always attempts to run all tests) + -Fix: run only those RTTs that have their plugins compiled + -Del: remove the breadboard tests for now: these input don't make much sense in that context + -Add: make clean removes everything from diff/ and out/ + -Add: export test: -v for verbose mode + -Add: in verbose mode, print all test names that failed + -Update: refs for the new padrot input and rounding error fixes + -Update: RTT: gerber refs for drill rounding bug fix and composite layers on mask + -Update: RTT: get gerber tests to export the csect + + [gtk] + -Fix: lib_gtk_hid shouldn't use the plugin control of lib_gtk_common (for cflags and ldflags) + -Fix: gl: composite layer stenciling + -Fix: gl: Disable thin-draw poly filling in the GL gui to match other HIDs + -Fix: board-preview sets board extents as drawing size for proper zoom + -Fix: undo bug: when gtk needs to run a getxy loop, it shall save the undo serial because the button release event in core is going to restore it + -Fix: route style crash on menu: get the menu updated when route styles change + -Fix: do not hardwire the .fp extension when saving a footprint, rather use what the io_plugin recommends + -Add: create tooltips for the mode buttons + -Add: make the DRC dialog reentrant + -Add: use the new fp save format conf setting to choose fp format we are going to use + -Change: DRC dialog uses the preview widget instead of pixbuf (portability) + + [doc] + -Add: pick and place and xy origin tutorial + -Add: implicit outline/origin board example for the xy origin tutorial + -Add: design files for via thermals and via shape styles + -Add: outline the user facing doc about pcb-rnd data + -Add: incomplete intro to the user data doc + -Add: initial v1.2.3 action reference appendix page + -Add: initial combined pcbfab/pcbCAD/pcb-rnd glossary + -Add: initial external resources links page + -Add: table of dialog behaviors + -Add: developer doc about polygon internals + -Update: bridges with 3 new io_; replace graphviz with aagraph + -Update: developer/data.html for subcircuits + + +pcb-rnd 1.2.3 (r8962) +~~~~~~~~~~~~~~~~~~~~~ + [core] + -Cleanup: start remove hardwired global var PCB, make the API take the board pointer as an argument + -Del: board color cache - use the conf + -Del: no need to set silk layer colors to special, draw.c will handle that + -Fix: human readable error message before abort() on unknown hid attrib type on cli-to-attrib conversion + -Fix: select element only if its silk layer is visible + -Del: show_paste is not a config setting anymore - normal layer group visibility should apply + -Fix: ElementList() shouldn't crash on empty footprint description (reported by Evan) + -Fix: don't segfault whenloading the buffer fails (e.g. source is non-existing file name) + + [layer] + -Add: compositing layer draw for mask, paste and silk; positive vs. negative, auto vs. manual flags per layer + -Cleanup: have a generic, draw-callback based PCB_LYT_DIALOG instead of a layer dedicated for fontsel; this makes it easier to introduce new dialog box layers/previews without having to register new layers + -Fix: uninit in layer_vis to remove events registered earlier + -Change: new interpretation of the mask draw API in the HID API: it's the generic composite layer draw API + -Add: EditLayer() and EditGroup actions for changing layer/group name and properites (+ dialog box) + -Add: function to clean up old imports: mark all silk layers auto; used in io_pcb, io_kicad*, io_eagle, io_hyp + -Cleanup: get rid of PCB->ElementOn in favor of a layer group based query + -Del: remove old config items show_mask and show_paste, use the normal layer visibility mechanism should handle that + -Split: split off LAYERVIS_CHANGED from the LAYERS_CHANGED event to provide a cheaper mechanism for the more common case + -Add: SelectLayer(): central action + -Add: low level group rename functions + -Add: low level function to find a group by name + -Add: low level group pointer -> ID converter function + -Add: low level function to step a layer within a group +1 or -1 slot; insertion of new layers is interpreted in group context,not in logical layer context + -Del: old layer move code: logical layer index is insignificant as layers are presented by group orders,no need to move layers on that list + -Add: helper function for creating the mandantory silk layers + -Add: ToggleView() can expand/collapse and vis/unvis all layers and groups + -Add: hid_common function for building a layer menu, at least adding groups and layers + -Fix: mark pcb changed when group properties are changed in EditGroup() + -Fix: cross section draws "text-with-background" only on the GUI - most exporters won't be able to display this correctly, making the text unreadable + + [layersel] + -Add: new layer selector in the top window; show layers per groups; collapse/expand groups + -Add: right-click layer popup (also selects the pointed layer) + -Add: layer property inidications similar to cross section view's: hatch for auto, thick border for negative + + [csect] + -Add: properly indicate where the layer would be inserted within the group + -Add: add/del/reorder logical layers within a layer group + -Add: allow logical layers to be in the paste layer + -Fix: allow all layers to show up on the csect drawing, not only copper layers + -Add: open popup menu for groups and layers on right click + -Add: draw_csect doesn't allow removing the last layer from a silk + + [eagle] + -Fix: make sure both silk layers are set up even if the input file didn't specify them + -Add: load and build polygons + -Fix: make new lines and arcs clear by default + -Add: use md_wire_wire for clearance values on lines and arcs + -Fix: put multiple unsupported layers on silk + -Add: proper element text placement and rotation + + [scconfig] + -Fix: cquote generates C89-safe long strings using arrays - removes a lot of string-too-long warnings + -Fix: use -ansi -pedantic for detections in --debug mode, so the same flags are used for detecting libs and compilation; this should fix the realpath bug reported by Ade + -Fix: make sure realpath() gets its _DEFAULT_SOURCE when needed + -Fix: -fPIC is optional: many C compilers don't support it + + [boardflip] + -Fix: don't mirror element text unless had to move to the other side + + [export] + -Fix: ps: proper plugin uninit + -Fix: stat: don't use read-only string in default attribute val - the gtk gui tends to free() it + -Fix: stat: user-input save metadata properly + -Fix: stat: use 4-digit year in date, to avoid confusion + -Fix: stat: wrong date format, should be iso (reported by Larry) + + [fp_board] + -Add: load board as a footprint library + + [fp_fs] + -Fix: always return error on fp mapping if topdir is not a directory - this how we give other fp_ implementations a chance to map those + + [gerber] + -Fix: board larger than 214.7mm had a coord overflow in drill files with 32 bit coords (reported by Evan) + + [gtk] + -Fix: pinout window size is 0 after opening + -Change: propedit preview should use the preview infra instead of pixmap for forward portability + -Change: menu: use hbox instead of the accel label hack copied from gschem + -Fix: popup menu didn't work since r4248: action didn't consider the extra layer of (private) menu handle + -Add: left-click on the layer selector widget pops up the layer popup + -Fix: gdk should allow drawing the paste layer + -Add: local widget_hide_all() implementation to work around gtk's wise decision to kill off everything that's simple + -Fix: don't offer restoring factory default for layers, it's hard to tell what exactly we should do + -Add: wt_preview can distinguish right click from pan + -Add: esc in command window dialog closes the dialog + -Fix: apply Chalres' patch about double command execution on esc + -Fix: point-cursor-disappears-if-gpmi-enabled bug; move point_cursor logics from glue to in_mouse, make a permanent override and an explicit "set cursor to mode default" (mode set to -1) that also respects the override + -Fix: command entry history upside-down + when number of commands is over the maximum in the history, properly delete the oldest, not the latest + -Del: underscore menu mnemonics: no support for that hotkey mechanism in our menus anymore + -Add: GL: annoying, bold warning about opengl not supporting composite layers + + [lesstif] + -Fix: non-c89 initialization + -Add: be able to show the paste layer + -Add: remember both submenu widget and menu button in the lihata node's user_data when creating menus (so that it'll be possible to remove menus later) + -Add: implement the remove menu HID call + -Fix: remove flags[] entry when a checkbox menu is removed + -Add: reuse empty wflags[] slots + + [io] + -Fix: let io_ set Data->loader on pcb load; this gives the plugin a chance to make a decision depending on file content + + [io_hyp] + -Change: enable the plugin by default + + [io_lihata] + -Add: v2 writer makes a layer stack subtree; prefer v2 saver if version is unspecified + -Fix: in-place upgrade from lihata board v1 to v2 (bypass the root mismatch error) + -Fix: non-lht-board file overwrite: missing or mismatching root error means we need to do a fresh save, not merging but overwriting everything + -Fix: when saving v1, make sure the 2 silk layers are at the end of the layer list - old code and the old format requires that + + [io_pcb] + -Fix: when loading a footprint file, properly set up the mostly empty layer stack + -Workaround: the total lack of reentrancy... assume fp fopen() may call Parse so initialize globals only after that call + -Fix: swap layers so that silks are always at the end (required by old code and the format) + + [plugin] + -Change: use puplug instead of the plugin system mostly inherited from mainline + -Change: switch over from manual plugin listing to semi-automated when generating the tmpasm + -Add: runtime plugin dependency handling: when a module is selected to be a plugin, its dependencies should be at least plugin (but don't need to be builtin) + + [png] + -Update: new mask draw API; properly draw both positive and negative combinations + -Fix: export non-axis-aligned square pads properly (numeric conversion bug turned those into random sized rectangles) + -Add: photo-mask-colour options similar to mainline's. + -Fix: draw mask layer in 'as shown' only if it's visible + + [polygon] + -Fix: enable DEBUGP() in --debug so we get more detailed error messages + -Fix: print animator script with proper coords on stderr instead of old pcb format lines when polygon asserts + + [ps] + -Add: remember last set mask mode + -Update: new layer mask API + + [route] + -Add: Allow line-points to be moved using the route code which implements 45/90 mode. Disabled by default with config setting move_linepoint_uses_route + -Fix: The 45/90 route rules were disabled if the rat layer was selected but editing other layers. + -Fix: original line end point move should manage undo in the new code when route is turned off (bisecting credits: miloh & evan) + -Fix: When moving a line-point would result in a 0 length line, the move operation was not applied. + + [rubberband] + -Fix: Draw rat lines directly when rubberbanding to avoid 45/90 rules. + -Fix: Rubberband with 45/90 route code failed if both ends of the line moved. + -Fix: plugin uninit should remove events registered on init + + [svg] + -Add: preparing for the new mask API: and sections for the mask + -Update: new mask layer API: mask set/clear overrides color + -Fix: use the "configured" mask color instead of hardwired red + -Fix: missing else made the silk use copper color + -Tune: "inner" layer shadow has no "3d" depth + -Fix: mask rendering logics: always visible in photo mode, group visibility controls it in normal mode + + [util] + -Del: gsch2pcb-rnd: method_pcb - please use method_import instead + + [tests] + -Update: simple gsch2pcb-rnd test: switch from -m pcb to -m import + -Update: pcbflags: there's no more showmask config setting + -Fix: missing distance calculation function - link misc_util.o in propedit test + + [doc] + -Update: core plugin howto for r8214 + -Fix: refine the 3-state wording in src_plugin's README + -Update: mods3; work from pup files, ignore the READMEs + -Update: plugin creation tutorial for the new plugin system + -Add: explain autoload in the plugin doc + -Add: mods3: generate plugin dep graph + -Fix: html validation, typos (by Larry) + -Update: model doc for layer compositing + -Add: missing rosetta Makefile + -Add: missing explanation for gpmi rosetta 90_clock + -Add: bugreporting howto + -Add: io_lihata: lihata board version history + +pcb-rnd 1.2.2 (r8120) +~~~~~~~~~~~~~~~~~~~~~ + [font] + -Add: multiple fonts: introduce the font kit concept; allow font objects to have a font id + -Add: io_lihata support for multiple fonts + -Add: io_lihata support for polygon and arc in font + -Add: font selector GUI + -Add: edit the current font, not font0, and throw an error if the current font is not accessible for some reason + -Add: alternative default font with arcs, Herhey font + + [export] + -Fix: ps: don't export zero-radius arc, it would end up writing "inf" after /0 (thanks to John for the bugreport and test file) + -Fix: svg: don't export 0-radius arc + -Fix: fidocadj: Fine tuned fidocadj text export angle, dimensions, placement + -Add: gerber: exporting the cross section layer is optional + + [footprints] + -Add: fp_wget: offline mode: wget the index only if enabled; GUI for manual update + -Add: fp_wget: support for edakrill + -Add: API CHANGE: the fp rehash function takes an optional pointer to the subtree to rehash; when NULL, rehash everything (as it did previously) + -Change: don't merge all local file system trees into fs, keep them separate for less confusion + + [layer] + -Fix: look up component and solder groups before placing a new rat on the GUI so the groups are placed right + -Fix: move action doesn't let the user remove silk layers + -Fix: removing a layer group removes all layers, including the second + -Fix: obsolete direct PCB ref + -Fix: when (re)moving layers, reparent the lists after memmove() to avoid broken parent pointers + -Fix: buffer operations (mirror and paste): use the buffer's layer list only if it has one - when copying a simple object within the board, there won't be, use the boards' then + -Cleanup: remove redundant pcb_layer_lookup_group() - use pcb_layer_get_group() instead + -Del: old API, already unused: pcb_layer_create_old() + -Del: macro PCB_LAYER_IS_EMPTY() to get the API simpler - just use the direct call, this also exposes the use of PCB in some calls + -Del: macro pcb_max_group() -> not PCB-safe + + [core] + -Fix: netlist add action shouldn't segfault on empty/NULL netname or pin name + -Fix: convert buffer to element: buggy layer group handling (made solder-side objects disappear; thanks to Evan for reporting this) + -Fix: move-selected undo bug: undo serial has to be increased after the paste + -Fix: Don't add a via when switching to/from a non-copper layer during line creation + -Fix: don't mess up the undo serial when moving an element to the other side from menu (reported by James) + -Change: increase the layer limit to 38 for new io_ plugins + -Change: move rectangle pad creation to a central function - more and more code depends on it + -Add: export version, revision and main paths so that child processes (e.g. parametric footprints) have a chance to identify the installation + + [io] + -Fix: io_lihata: assign unique ID to each polygon point loaded - fixes poly point move undo bug + -Fix: io_kicad: parser now copes with absent gr_line thickness definitions + -Fix: io_kicad: save fp in s-expression format + -Fix: io_kicad: quote module name, as it may contain () + -Fix: io_pcb: do not load empty footprint into the buffer, it'd assert later (fixes: parametric footprint with broken params was leading to an assert in the preview) + -Fix: io_pcb: force-rename outline and silk layers because the loader will detect them by name + -Fix: io_lihata: accept trailing whitespace in boolean values + -Fix: io_lihata: don't complain about fonts under io_err_inhibit + -Add: io_kicad: eeschema import + -Add: io_kicad: recognize layers Top and Bottom + -Add: io_pcb: improvise a minimal usable layer group setup if there's no layer group string on the input (thanks to oskay for reporting this) + -Add: tEDAx: netlist import + -Add: tEDAx: footprint export + -Add: tEDAx: footprint import + -Add: mentor: plugin for importing edf netlist from Mentor Graphics Design Capture + + + [rubberband & route] + -Add: keep line direction of middle line segments (2 lines connected) in rubber band mode (patch by Luis de Arquer) + -Add: Rubberband keep direction: Line being moved is constrained to keep direction on preview + -Add: optional curved corners; alt+c and alt+shift+c in menu files to change route arc radius + + [gtk] + -Fix: external command window segfault when reopen after a WM close + -Fix: preferences dialog: proper refresh of widgets when changing the unit in top window while the sizes tab is open + -Fix: fit in 800x600 + -Fix: cancel means NO when prompted for creating a new layout (updated ghid_prompt_for() for r7792) + -Fix: don't change the mouse cursor in busy mode if the hid is not initialized (led to crash) + -Fix: Display the proper pcb-rnd icon for top level windows. + -Fix: preferences window: preserve correct tree view selection after Save. + -Add: gl support + -Add: optional gtk shift workaround for some broken mac+gtk stack + -Add: detect if the user clicked on a parametric footprint and present a dialog box with its parameters + -Add: gtk's attribute dialog can notify the caller about changes using an optional callback function + -Add: global or selective refresh of libraries using the refresh button + + [lesstif] + - double buffer preview + + [scconfig] + -Fix: make clean removes sccbox.o + -Fix: generate all files so that make dep works right even with disabled plugins + -Cleanup: move out 60 kilobytes of optional junk from Makefile to Makefile.gendep: we may depend on make -f and variable passing if we already depend on gcc for make dep + -Cleanup: move compile templates to scconfig/template + -Cleanup: rename globals VERSION, REVISION and PACKAGE to have a PCB_ prefix to avoid name collisions + + [pcblib] + -Add: auto generated --help for all parametrics + + [djopt] + -Fix: uninitialized local vars (reported by miloh) + + [boardflip] + -Change: rewrite the board flip plugin to be generic (flipping around X and/or Y, applying offsets) + + [pcblib] + -Fix: unit conversion supports all suffixes the core supports + + +pcb-rnd 1.2.1 (r6916) +~~~~~~~~~~~~~~~~~~~~~ + [layer] + -Cleanup: better layer group support; clear separation of physical and logical layers; real and explicit layer stack concept + -Fix: remove silk and component and solder assumptuion from crosshair and search + -Fix: auto enforce drc only on copper layers, remove silk assumption + -Fix: autorouter refuses to route on outline; also remove silk assumptions + -Fix: teardrop works only on copper layers + -Add: cross-section view: an userfriendly, a common, HID-independent mechanism for layer group edit + + [random i/o and the ecosystem concept] + -Add: export_fidocadj + -Rewrite: import_dsn, proper parser + -Add: import_ltspice + -Add: import_mucs + -Add: import_tinycad + -Add: import_ltspice: parse a mentor netlist + -Workaround: SVG: near-360 degree arcs break some of the rendering engines + + [core] + -Add: accept # comments in action scripts + -Add: self contained pcb-rnd executable: embedded font and default.pcb + -Fix: Draw the correct pin/via shape when the SQUARE flag is set in thin-draw mode + -Fix: NoHolesValid cache bit set bug that made silk polys disappear + -Fix: do not attempt to calculate bbox of empty elements - throw an error instead and ignore the element (or even assert, in --debug) + -Fix: don't depend on layer name for outline + -Fix: don't let negative clearance happen + -Fix: layer max assert off-by-1 - really allow 16 layers + -Fix: polygon arc rounding error when drawing clearance around a pad + -Fix: polygon drawn using the poly tool caused crash on save due to overwriting the list-administration when copying corsshair-poly to newly allocated layer poly + -Fix: redraw after pin number/name change to get the change displayed + -Fix: refuse to create attribute with NULL or empty name + -Fix: remove arc endpoint should remove the arc, just like with lines + -Fix: when deriving default file name of the board, don't truncate hardwired .pcb, try all io's file extensions until the first that is there + + [arc] + -Fix: arc-in-box macro uses the real bounding box of arcs so an arc can be selected by a positive selection box just barely embedding it + + [doc] + -Fix: html validation and cleanups + + [drc] + -Add: Draw DRC outline of pads when enabled + -Fix: Draw DRC outline when moving lines + -Fix: Improve the drawing of the DRC outline around pins and vias + -Fix: When moving an Arc, draw the DRC outline if enabled. Draw the Arc as an outline instead of thin + -Fix: When moving vias, draw the DRC outline when enabled + + [dynstyle] + -Fix: when a new style is created, the gtk-side cache needs to be regenerated + + + [export_gerber] + -Add: copy hackvana extensions from mainline + -Fix: eagle file suffix bug made top layer and bottom copper layer clash with top and bottom silk + + [export_png] + -Fix: notice gc color and cap style changes and update the brush + -Fix: properly draw corner case: full-circle arcs + -Fix: scale rouding bugs + -Fix: use gc for zero-length arcs too + + [gsch2pcb-rnd] + -Fix: don't depend on scconfig objects, use pcb_concat() instead of str_concat() + -Fix: stop fighting with src/ for compiling the src_3rd/ objects, just call src/ for doing that + + [hid_gtk] + -Split: hid_gtk common parts into a lib (lib_gtk_common) + -Fix: arc delta angle > 360 means full curcle, don't modulo + -Fix: arc endpoint rounding error when drawing with gdk (reported by Evan) + -Fix: don't run the netlist window if gtkhid is not yet active (batch mode) + -Fix: set the right layer color when changing layer colors - store the context struct for each layer index separately (more memory leaks...) + -Del: unused ghid_dialog_confirm_all() and ghid_dialog_confirm() + -Del: utf8 dup string is not even used anywhere + -Del: free_glist_and_data() is not in use, get rid of it + -Del: dead code: ghid message dialog: we use the log now, that should be the only one way to inform the user + -Del: unused abort functions + -Del: gui-keyref dialog (outdated, hardwired, unaccessible) + -Change: About dialog is more gtkish and uses the pcb-rnd logo + -Change: disable mnemonics for main menus because mnemonics lets gtk steal our keyboard input + + [hid_lesstif] + -Fix: arc delta angle > 360 is always a full circle, don't modulo + -Fix: don't try to change cursor shape for being busy if the hid is not running + -Fix: typo in the menu config for show_mask made solder mask unable to display + + [io_kicad] + -Change: use the new, simpler layer creation API + -Fix: refuse to use any negative layer + -Fix: residual arc format parsing errors; homeomorphic linear mappings R us. + -Fix: empty altium2kicad element definitions now imported with a 1nm line at the module centroid + -Fix: fixed non cummutative symmetry operations when importing fp_arc and gr_arc elements + -Fix: fixed off by one tree traversal error for polygonal zones + -Add: Kicad supports arcs on the Edge.Cut layer, now implemented + -Add: accept # comments when reading a KiCad s-expr file + -Add: improved handling of SMD layer definitions board + + [io_lihata] + -Fix: default output formatting (indentation bugs) + -Fix: properly load the outline layer, even if it appears to be in group -1 + -Fix: translate the new, rich layer group table to the old, dummy format for saving v1 + + [io_pcb] + -Fix: don't attempt to save attrib with NULL value + -Fix: layer number boundary check bug (the legacy +2) + + [poly] + -Fix: poly clipped out of existence can come back without an assert + -Fix: when priting 'cleared out of exitence' message, use mm for coords + + [res] + -Add: all new importes in the import menu + -Change: default file menu rearranged, import options grouped in a submenu to keep things simpler + + [rubberband] + -Add: Support rubberbanding of lines attached to an arc + -Fix: Allow both ends of a line to be included in a rubberband move + + [scconfig] + -Add: detect and use -std=c99 if available, some versions of gcc doesn't go for that by default - we also want to avoid accidentally using extensions in C99 code + -Add: detect cairo for the breadboard exporter + -Fix: allow parallel build + -Fix: mod CLEANFILES takes effect now + -Fix: when compiling with --debug, display debug symbols as implicit-enabled in the summary + + [toporouter] + -Del: remove toporouter and gts - we have better alternatives now + + +pcb-rnd 1.2.0 (r5967) +~~~~~~~~~~~~~~~~~~~~~ + [unravel] + - Cleanup: reorganize the code around object types instead of the old, action-oriented approach + - Cleanup: prefix almost all core symbols with pcb_ or PCB_ so the code can be reused as a lib later + + [doc] + -Add: start writing a new user doc + + [arc] + -Fix: broken is-point-on-arc check for large angles (thanks Evan for the bugreport) + -Add: angle/radius edit UI + + [conf] + -Fix: don't crash on empty project file + -Fix: when creating a new project file root, use the geda project file hash, not the pcb-rnd-config node - the project file is shared among programs + + [gerber] + -Fix: emulate 0 long arc with a 0 long line to work around a gerbv bug + -Fix: simpler "do we print this layer?" logics, without caching + -Workaround: split >180 deg arcs because some viewers (e.g. gerbv) have hard time interpreting them + + [gtk] + -Fix: route style logics: start out with the copy of style 0; after a deletion inherit the sizes from the deleted style + -Fix: don't reuse the static conf chg binding struct of fullscreen with solder side swap - it'll probably ruin both + -Fix: update bottom status line after flipping the board + + [mods] + -Move: drill.[ch] to the report plugin + -Move: original rubberband code into a feature plugin + -Cleanup: convert some GUI HID actions to events so that multiple GUIs can bind to them + -Add: plugin frame for import_hyp + -Add: remote plugin (HID-level remote control over sockets) + -Add: draw_fab plugin behind a stub, move draw fab code from core to the new plugin + -Add: new export plugin: export_stat (board statistics) + + [io] + -Add: an extra flag bit to allow non-fatal loads; make sure missing default.pcb doesn't generate an error message + -Add: proper handling of multiple file formats and file name extensions + -Fix: add new test parse call - fixes false alarm parser error messages + -Fix: don't change format on backup and tmp saves + -Fix: don't throw the "no font" warnign after loading a footprint because footprints are expected not to have font embedded + + [io_kicad] + - Save and load in the kicad s-expression format + + [io_lihata] + -Fix: don't save invalid nodes in the canonical format (backup saves) + -Add: (somewhat selectively) save and load the config subtree + -Add: one more emergency save on lihata merge failure and verbose error message with instructions + + [layer] + -Cleanup: convert magic number macros to enum + -Cleanup: introduce layer id and layer group id types + -Cleanup: more explicit virtual layers + -Cleanup: remove the old layer API, including all the SL_ macros + -Cleanup: renames and refactoring to make the logical layer vs. physical layer concept more clear + -Split: move layer visibility (stack) functions out of layer.c + -Rename: mask layer names: use top/bottom instead of component/solder for consistency + -Add: UI layers (dynamic allocated debug layers with permanent objects) + -Add: new layer name generator, based on flags and virtual layer names + + [pcblib-param] + -Fix: don't lose pad thickness unit when calculating new defaults for qf() + -Change: center pad of qf() is generated with no-paste (requested by John G) + -Add: qf() center pad paste matrix option (requested by John G) + -Add: qf() central pad mask option with cpad_mask; when not set, calculate it from pad geometry + -Add: qf() got a new rpad_round boolean; when manually set to true, generates round pads + + [svg] + -Fix: arc support: use the large and sweep flags of svg path arc to get true PCB arcs + -Workaround: full circle arcs - the two endpoints should differ + -Workaround: make endpoints differ in a 0 deg long arc + + [tests] + -Cleanup: update and enable most of the tests, unified output, central make test + + [util] + -Add: prj2lht: script to convert old projects to new + -Fix: install the import schematics scm script in our own LIBDIR, because it's not reliable to find the gschem installation, rather use -L for gnetlist + + [scconfig] + -Change: use $(MAKE) instead of make - this allows GNU make to run recursive parallel compilations (reported by Dima) + -Change: disable bison by default; use --enable-bison for developing the grammar + -Change: do not use gts for anything if toporouter is not configured + -Add: extra error if explicitly requested things differ from the results we got + -Add: make clean/distclean removes more scconfig related leftovers + -Add: optional support for DESTDIR for Debian + + [core] + -Fix: C89: do not depend on or strcasecmp, implement our own + -Fix: HID API bug: invalidate_lr needs pcb_coord_t instead of int + -Fix: action Netlist() subcommand add modifies the INPUT netlist, not the EDITED because this is used bu import_sch + -Fix: attribute deletion by index didn't move all items properly (affects mainline as well) + -Fix: disable cycledrag when rubberband is enabled (they are incompatible) + -Fix: don't close a polygon twice on normal finish (fixes the excess need 3-point error message) + -Fix: don't crash when a pin/pad number is NULL + -Fix: don't warn for second hit on a plugin already loaded as long as the hash is the same + -Fix: get rid of pointerlist in favor of vtptr + -Fix: incorrect flag struct comparison; may have caused unpredictable undo bugs + -Fix: line-line intersect code detects and handles the corner case of parallel lines properly (checking wheter endpoints of lines are on the other line) + -Fix: make data bounding box function reentrant + -Fix: make move macros safer with the standard do { } while(0) wrapping + -Fix: make text, arc, line, pad, pin/via move macro safe: don't evaluate arguments twice, wrap in do {} while + -Fix: move an object by 0 pixels shouldn't inhibit all subsequent redraw + -Fix: negative selection box: limit box coord orders to two canonical forms, one positive, and one negative (fixes north-east to south-west selection on component-side view) + -Fix: pin move is really the same thing as via move, use the same macro + -Fix: polygon mirror should update the rtree (reported by Chad) + -Fix: rename old, gui-hid-defined Export() actions to ExportGUI (matching the ImportGUI()) - Export() is the name of the builtin, core action + -Fix: text rtree handling bug: EraseText should NOT have the side effect of removing the text from the rtree but the callers should do all rtree manipulation as needed + -Fix: undo text flag bug: add text join undo as text flag change, not as line flag change + -Fix: update rtree when mirroring arc in buffer + -Fix: use COORD_MAX for large coord values, don't assume coords will be 32 bits + -Fix: use the hid name passed with --gui, even if --gui is not the first argument; also allow using --hid instead of --gui (less confusing) + -Fix: when snap off, don't crash when action helper is trying to figure the endpoint of an arc + -Cleanup: classify all messages to be warnings, errors or info - no more PCB_MSG_DEFAULT + -Cleanup: remove unsafe (non-reentrant) arc ends query + -Add: --dump-plugins --dump-plugindirs CLI commands and DumpPlugins() and DumpPluginDirs() actions + -Add: central Export() action instead of gui-specific ones - this works without a GUI HID + -Add: conf setting to disable negative-box selection + -Add: conf setting to make negative-box selection symmetric (ignore Y coord sign) + -Add: support route style attributes + +pcb-rnd 1.1.4 +~~~~~~~~~~~~~ + (1.1.4 is really an 1.1.3 with some bugfixes backported from 1.2.0) + + [gsch2pcb-rnd] + -Add: method infrastructure + -Add: a method that uses the same mechanism as import_sch + -Add: a method that uses import_sch's gnetlist backend for elements but a the usual PCB backend for the netlist + + [import_sch] + -Fix: install and use the .scm script from our own directory instead of guessing gnetlist's installation + + [debian] + -Del: remove debian/ to ease official packaging + +pcb-rnd 1.1.3 (r4479) +~~~~~~~~~~~~~~~~~~~~~ + [mods] + -Fix: the IO system remembers which format (plugin) a file is loaded or last saved with and uses that on a 'save' instead of the default one, unless a different format is explicitly requested ('save as') + -Fix: load plugins from /usr/lib/pcb-rnd/plugins instead of /usr/lib/pcb/plugins + -Fix: macro argument bug in fontmode (thanks Chad!) + -Fix: import_sch: rename the gschem forward-annotation script so that it doesn't collide with mainline's + -Cleanup: rename legacy_func to lib_legacy_func as part of the plugin lib cleanup + -Add: io_kicad: load and save kicad s-expression board layout files + -Add: io_kicad_legacy: save boards and/or modules in the old kicad format + -Add: io_lihata: preserve formatting and numeric format on load/save + -Add: io_lihata: custom indentation rules for boards (more compact, easier to read) + -Add: in export_xy: code from mainline to support IPC-7351 on element rotation guesses + -Import: autocrop original code + -Import: boardflip + -Import: distalign + -Import: distaligntext + -Import: jostle + -Import: polycombine + -Import: polystich + -Import: renumberblock (as part of the renumber plugin) + -Import: smartdisperse + -Import: teardrops + -Import: bboard exporter from git + -Import: dsn exporter from git + -Import: dxf exporter + -Import: ipcd356 exporter from git + -Import: openscad exporter from git + + [query] + -Add: query language - select/unselect objects using expressions + -Add: advanced search dialog box frontend for the query language in the GTK HID + + [core] + -Cleanup: const correctness on net creation: style is read-only + -Cleanup: move generic find-net-for-pin function from rats_patch to netlist + -Fix: changing grid should not only change it in PCB but also in the conf tree - this will deliver the conf change event that will trigger the update in gtk + -Fix: const correctness in hid_flags, pin-to-net lookups + -Fix: coord conversion rounding errors + -Fix: deselect not incrementing undo serial number (from Charles Parker); caused undo panic upon undoing a deselection + -Fix: invalid function ptr to data ptr casts + -Fix: move global netlist states from global variables to PCB struct fields (on the way to a proper lib...) + -Fix: rubber band: when move didn't happen, flags were left behind + -Fix: undo element text size bug + -Fix: plug_io file load: when multiple formats matched an explicit load format description, try them all, until one worked + -Split: generalize format-string-like variable substitution so it's easier to build custom file names (and other strings) from config templates; supports %F (file name), %N (board name), %T (UNIX time), %B (basename) and %D (dirname) + -Add: remove_menu concept in HID API + -Add: generic flag change macro that can set, clear or toggle the flag depending on an argument + -Add: hid export option to draw holes after all copper, silk and mask layers has been drawn so that holes punch through everything + -Add: layer creation and rename helper functions + -Add: obj_any - a generic type+union struct (and a list of that) for holding pcb objects of any kind + -Import: LookupConnectionByPin from mainline + -Import: clear flags by object type from mainline (import and port) + + [debian] + -Change: redo the whole script for a modular packaging of plugins + + [util] + -Add: devhelper script for testing round trips + -Add: pcb-strip (remove attributes and/or symbols from a .pcb) + + [gtk] + -Add: full screen button in the scroll-bar corner + -Fix: call the checkbox menu update function from conf change callback installed at menus, instead of assuming checkbox states are changed only from within the GUI and calling the updater directly + + [propedit] + -Add: text set applies on element texts too + + [res] + -Add: RemoveMenu() action + -Add: gtk can remove menus + -Add: update_on field - bind checkbox updating to a config var + + [scconfig] + -Fix: when generating dependency generator rules, use -MT for src_3rd targets or else gcc will ruin the target object names; this means proper dependencies in src_3rd + -Cleanup: use bison/flex output file name CLI arguments instead of the tmp/mv hacks - the code depended on bison anyway + -Add: --symbols to enable debug symbols without the extra asserts and -O0 + +pcb-rnd 1.1.2 (r3773) +~~~~~~~~~~~~~~~~~~~~~ + [cleanup] + - ANSI/C89 compliance + - char * const correctness + + [mods] + -Fix: io_pcb: do not convert measure through int (Chris' mm grid bug) + -Fix: import_sch: generate proper error messages if there's no make or gnetlist program configured + -Fix: io: qsort cmp function API bug - wrong format preference + -Fix: io: make sure the PCBChanged action is ran on revert so that route styles and other properties are updated + -Fix: fontmode broken coord-to-cell conversion rendered the font editor useless + -Cleanup: export_bom and export_xy are separate plugins; export_xy depends on export_bom because of the name escaping function + -Rename: debug plugin to diag plugin to avoid confision with --debug in ./configure command line + -Add: diag: layer dump action + -Add: diag: evalconf() action to evaluate the configuration situation of a path + -Add: io_kicad_legacy: first steps for PCB layout implemented. Mildly broken module exported. + -Add: propedit: object property editor (with gtk support) + -Add: io_lihata: initial implementation without object ordering + -Add: io_pcb: 3 different flavors of the original format (using different numeric formats) + -Add: import_sch: make and gnetlist programs configured in the default config + + [lesstif] + -Fix: compile and link even if xrender is not found + -Fix: print angle as %f in the status line as it's a floating point value + + [gtk] + -Fix: library selection window switches to arrow mode before replacing the buffer, so that the outline drawing code doesn't get confused + -Fix: library path file chooser should be a "folder chooser" not a "file chooser" + -Fix: display the correct $(path) syntax in the library window help + -Fix: when file name changes, update window title + -Fix: do not allow to zoom out so much that Coord can't handle it anymore and overflows + -Fix: work around the control bug on some mac systems + -Fix: do not draw global grid beyond board edges + -Fix: shift+tab: translate left-tab back to tab, shift is handled by the core + -Fix: when popping up the log window for a Message(), don't raise it so focus is not stolen (especially if it's already up) + -Fix: when the main window is closed while the command entry main loop is running, quit the CLI main loop first, so the Quit action can execute and break the outer main loop of the GUI + -Fix: mark the PCB changed when the route style changes so it's saved + -Add: a delete option to the route style selector + -Add: explicit route style (pen style) for sizes diverged from any known style + -Add: finish gtk preferences dialog's "Config PoV" subtree + -Add: "save as" dialog with file format widget + -Add: remember preferences tree expansion and other states when the dialog box needs to be rebooted + -Add: implement fullscreen mode + -Add: local grid implementation: optionally draw grid only in a small radius around the crosshair instead of on the whole screen (speeds up sw rendering on large screen) + -Add: global grid can be sparse (drawing every Nth grid point only); min distance is a configuration item + -Change: match gtk status line style with elegant lesstif status line + + [scconfig] + -Fix: use generic code for plugin vs. plugin dependencies, deps are coded as data + -Fix: various portability fixes for a working IRIX port + -Add: revtest and revision stamps - this tool will let Makefile automatically request the user to reconfigure + -Add: central distclean cleans src_3rd/ + -Add: --workaround-* system, with a gtk-ctrl workaround + -Add: new cli arg for mass-enabling/disabling all plugins: --all=* + + [core] + -Fix: hid input mouse scroll mixup: up and down were for scroll but left and right were for buttons. Prefix all scroll names with "scroll" (fixes macos pan-zoom-select bug) + -Fix: cancel on "new pcb" makes sure PCB never ends up NULL; worst case it tries to create an empty PCB to fall back on or exits with a fatal error if even that fails + -Fix: funchash should be case-insensitive (case insensitive actions and params) + -Fix: introduce pcb_cardinal_t instead of redeclaring X's Cardinal + -Fix: cursor position is Coord, not long - long won't work on 64 bit coords + -Fix: initialize builtins before loading plugins so later buildin <-> plugin collision can be resolved by not loading the plugin + -Fix: full-polygons are sensitive when clicked on the "clipped away" part + -Fix: non-refactored line drc enforcement + -Fix: qsort cmp function return value bug - wrong ordering of sources for the merge + -Add: RouteStyle() action accepts style name, not only index + -Add: action, change and undo code for chaning arc radii (width and height really) and start/delta angles + -Add: new, future-proof layer API, phasing out the old API + -Add: close polygon if the user clicks twice on the same point ('doubleclick'; like with the line tool; thanks to hzeller) + -Add: message log entries have severity levels; user can configure color and whether the message log should pop up for each severity + -Add: pcb-printf %mH prints human readable metric or imperial coords + -Add: inhibit draw counter: when moving an element with all rubber bands (e.g. netlists) attached, inhibit redraw them individually, redraw only once, at the end + -Add: reenable signals as detected by scconfig so that emergency save can run on crash + -Change: attribute list in all object types + -Split: layer.[ch] from misc.[ch]; the layer code is large and complex enough to get an own module; it's also in-line with the module-per-object-type idea + + [util] + -Add: workaround script to comment out #warnings in a source file (for real C89 targets) + -Add: gsch2pcb-rnd: warn for old config overriding pcb-rnd search paths + -Add: install gnet pcb forward backend so that import_sch works out of the box + +pcb-rnd 1.1.1 (r2683) +~~~~~~~~~~~~~ + [io_kicad_legacy] + - Add: save paste buffer elements to kicad (legacy) .mod as native format + + [scconfig] + -Change: remove config.manul.h (use scconfig CLI args instead), rename config.auto.h to config.h + -Change: coord type, the corresponding MAX value and abs() function should not be set manually in config.manual.h; ./configure --coord=32 or --coord=64 sets these all, 32 being the default value for now + -Change: move the dot_pcb_rnd setting from manual config header to scconfig (CLI arg) + -Fix: don't attempt to use -rdynamic for compilation, only for linking + -Fix: accept that IS_LNK may not be set (using conditional variable reference) + -Fix: working cross-compilation: proper separation of host and target tools (cp, ln, ar and friends are part of the build system, use the host version) + -Add: ./configure --enable-dmalloc detects dmalloc + -Add: detect dbus and compile the plugin if enabled + -Add: windows port: detect LoadLibrary(), _getcwd()/getwd(), _spawnvp, getpwuid, realpath, rint(), mkdtemp and mkdir/_mkdir + -Cleanup: split up config.auto.h.in: move dbus related item to dbus and gl related items to gtkhid-gl to keep central part plugin-neutral + -Cleanup: stop using HAVE_WHATEVER_H, rahter generate the #includes per function + + [core] + -API change: rtree returns success and optionally sets the number of objects found - this allows the caller to avoid long jumps to stop the search at the first hit + -Fix: action names are case-insensitive again + -Fix: don't crash if select-by-text gets empty name or cancel + -Fix: undo crashes/asserts for updating NULL rtree with selected element text + -Split: huge find.c in smaller files, per topic + -Change: use genregex minilib instead of POSIX regex, for better portability + -Cleanup: remove find.c dead code + -Cleanup: rtree API names return values instead of using 0..1 + -Cleanup: const correctness in EvaluateFileName + -Cleanup: introduce pcb_rnd(), which is a wrapper around rand() (or optionally, random()). rand() is portable, but on some very old system may be weak. + -Cleanup: introduce pcb_strdup() and pcb_strndup() and avoid using non-C89 libc calls + -Cleanup: always provide pcb_mkdir() as a portability wrapper around mkdir; all code should use this instead of mkdir() + -Cleanup: remove #ifdef wrapping of standard C89 header #includes - it's reasonable to assume/require proper C89 support more than 25 years after the standard came out + -Cleanup: a set of unused/obsolete #includes + -Cleanup: convert const.h #defines into enums (for the type, namespace and debugging); also proper name prefixing + -Cleanup: move route-style specific function from action-oriented set.c to object-oriented route-style.c + -Cleanup: rename SwapBuffers to pcb_swap_buffers for proper prefixing (win32 API name collision) + -Add: central function for looking up a routing style using a sparse list of properties + + [gtk] + -Fix: gtk gdk background image drawing: clip for negative pan to avoid artifacts and segfault + -Fix: remember Messages() that are written before the message window is set up and append them in the window when it is already constructed + -Fix: do not crash if there is no route style defined, just go with an empty style section and let the user create new styles + -Fix: rework the win32-workarounds for corss-compiling + -Fix: always update bottom style printout when the style changes, even if there's no matching stock style (thanks to miloh for reporting this) + -Add: a mandatory route style to indicate non-matching types (hidden in the menu) + -Add: optional file format combo box on the save as dialog + -Change: use round radio buttons instead of rectangular toggle buttons for the layer preferences table - on some setups gtk theme made the buttons unreadable + + [mods] + -Add: import plugin API + -Add: new features in the I/O API to support user-selected output format and listing available formats + -Split: move out netlist read from the io plug code to a separate import plugin + -Cleanup: remove edif stub, convert edif to an import plugin + -Cleanup: do not attempt to extract password entries manually in random plugins, use the central user name retrival function - easier to port, heuristics not duplicated + -Cleanup: ps export: get rid of non-portable alloca() - polygrid is used rarely, performance penalty of malloc() should not be a problem + -Cleanup: pcb I/O: do not use non-portable bzero, prefer memset() + -Fix: dbus: if there's no GUI by the time dbus is uninitialized, don't call it + + [doc-rnd] + -Split: move out developer docs from doc-rnd/ to doc-rnd/hacking + -Add: windows cross-compilation notes + -Add: hacking doc for writing importers (incldues a description of the main pcb data structures) + + [conf] + -Fix: gtk gui preferences saves editor/auto_place in the config file + -Fix: gtk preferences' general tab should also save editor/save_in_tmp + + [w32] + -Add: minipack: recipe for pkg-config + -Fix: minipack: calculate output filename for wget so that ?download suffix can be truncated + -Fix: minipack: don't attempt to build pcb-rnd from minipack (policy: minipack builds all deps then we crosscompile pcb-rnd) + -Update: minipack: gd and tiff recipes for newer versions + +pcb-rnd 1.1.0 +~~~~~~~~~~~~~ + [conf] - full rewrite of the config settings subsystem + - Del: settings, color files, preferences - everything is in the conf system from now + - Add: config settings are stored in structured lihata files on different levels + - Add: all config setting are equal - they can be stored in system, user, project or design file + + [core] - cleanup + -Fix: editing text should properly update the rtree + -Fix: Display(PinOrPadName) doesn't use crosshair directly, without checking validity, but uses getxy which asks the user in turn, if the crosshair is invalid + -Fix: ortho draw lines, polys and poly holes did not update last drawn point and generally did not work + + -Cleanup: remove a bunch of excess #includes to reduce the amount of deps + -Cleanup: rename keepaway to clearance; terminology: clearance is copper vs. copper spacing; keepaway is any other spacing + -Cleanup: generic dead-code and compiler warning removal + -Change: menus: make a new Maintenance submenu in the File menu, move printer calibration and library rescan there + + [poly] - bugfix + -Fix: don't xor-overdraw the first line of a poly rubber band while drawing the second line so it doesn't cancel itself out + -Fix: first click of the poly hole is also the first point of the hole + -Fix: reset attached object state after finishing a poly hole so that the second hole doesn't start in invalid state (caused poly duplication) + -Fix: don't let the user start drawing a poly hole if first click is not a poly + -Add: draw assumed closing rubber band line dashed + + [dynstyle] + -Fix: number of styles is not limited anymore (styles is a dynamic vector) + + [res] + -Fix: dynamic menu insertion bug: don't add new level if it is already added + + [mods] + -Fix: report doesn't crash if there's nothing to report + -Add: debug plugin to host core debugging actions so that they can be removed from core + -Add: debug plugin to tmpasm lists + -Add: io_* hooks - native file formats are plugins now + -Change: turn .pcb (.fp) file IO code into plugin io_pcb + -Add: io_pcb can save (CFR_DESIGN) config in the design as attributes + -Add: central infrastructure for per plugin help (usage), plus the help text in each plugin + -Add: fp_rehash() action to trigger a rehash + + [gtk] + -Fix: double-zoom GUI lockup, pan+scroll wheel lockup + -Fix: shift+mouse click should work + -Fix: preferences window now easily fit in 800x600 + -Fix: don't destroy the tooptip timer when it destroys itself - fixes the famous tooltip glib warning + -Fix: gtk warning/assert introduced by r1439: toolbar can not be a vbox, the parent vbox needs to be tracket separately + -Fix: abs() handling with non-int types - more proper handling of coords on corner cases like tiny objects (contributed by Chris Smith) + -Cleanup: dialog titles should be pcb-rnd, not PCB + -Add: properly remember window positions and sizes, save and reload them if the user enabled the feature + + [scconfig] + -Fix: really compile if there's no glib installed and no glib-dependent plugin selected + -Fix: remove m4 bin from config.h template - no code uses this anymore; do not even detect m4, it's not needed anywhere + -Fix: reorder link command for the main executable so that libs end up at the end of the link list (some linkers are sensitive to this) + -Fix: various random fixes for a mac port + -Del: hid.conf: not needed anymore, hid types are managed differently + -Cleanup: C89 always has atexit() and there's no on_exit + -Add: --debug (that shoudl enable asserts and -g) and a tmpasm script to set cflags accordingly + -Add: detect gettext if intl is requested + -Add: detect bison/flex (with an option to disable it) + +pcb-rnd 1.0.10 +~~~~~~~~~~~~~~ + [res] - resource->lihata conversion + -Add: new action: CreateMenu() + -Add: centralized hid keyboard handling API + -Add: optional: a gtk-clone multi-key capable menu file that copies gschem's hotkeys mostly + -Change: remove res parser, use lihata instead; affected plugins: hid_gtk, hid_lesstif, vendordrill + -API CHANGE: dynamic create menu call API takes a string path, not an already splitted array + -Update: keylist html generator util works from lihata and handles multikey + -Fix: remove hardwired layer selection key bindings, use configured hotkeys (alternative menu files may want to use the same keys differently, hardwired keys are bad) + + [library_t] - library data structure cleanup/rewrite + - Change: replace MenuEntry and related code to a library_t + - Add: allow a generic tree representation in footprint library + + [reduce] - reduce code size without losing actual functionality + -Del: extern "C": pcb is a pure C project, if someone wants to include headers from whatever other language, he should take care of it on that side + -API CHANGE: rewrite action_funchash to not use custom local hash but genht and to offer cookie based namespaces for modules + -Cleanup: rename action_funclist to funchash_core_list to decouple functions from actions + + [scconfig] + -Fix: scconfig/build doesnt' fail even if lesstif is not installed + -Fix: do not attempt to detect libgtk is the gtk hid is disabled + -Fix: don't detect gd if it's not needed; disable exporters that depend on GD if required parts are not available + -Fix: relax gcode/nelma png requirements: print a warning about reduced functionality but let them compile if there's no png but gd is present + -Fix: get the dep file sorted by target; this should avoid unintended changes introduced by unordered lists + -Change: split up the tmpasm list of modules so that it's easier to get gsch2pcb link again using whatever backend plugins + -Cleanup: move strflags test code to regression/ + -Change: portability, realpath are compat_*; compat.[ch] split to _dl and _misc + -Move: remove Makefile.in.mod, move module tmpasm files to src_plugins/ + -Add: detect libstroke and compile with the right cflags and ldflags + -Add: tool to quote files into C strings; generate compiled-in, C versions of the new lht menu files, per hid + + [mods] + -Add: API to remove functions by cookie + -Add: print warning if a module leaves anything in the func hash at exit + -Add: infrastructure for switching from one gui to another + -Add: fp_wget: web based footprint implementation, gedasymbols.org integration + -Move: command.[ch] to a shorthand command plugin (shand_cmd) + -Move: report to a feature plugin + -Move: fp_fs plugin: separate footprint code from file.[ch] + -Move: move debug actions from lesstif to comomn "oldactions" as they are not GUI-dependant and might be generally useful + -Move: hid/common/ to core hid_*, split up large, random collections of functions by purpose + -Move: split and rename action.[ch] to make room for hid-common actions.[ch] in core and avoid confusion in names; rename actions.h to hid_actions.h for naming consistency + -Move: HIDs to plugins, removing the hid/ directory + -Move: hidgl to a separate plugin (to be compiled later) + -Fix: event unbind shouldn't segfault if multiple adjacent events are free'd + -Fix: event_bind() takes cookie as const char *, not as void * to comform the convention + -Fix: hids install and uninstall actions, flags and attributes only around their do_export main loop so they don't conflict + + [leak] - cleaning up memory leaks + -Add: hid attribute remove by cookie + -Fix: lesstif and gtk hids remove their attributes + -Fix: vendordrill free()s all cache memory used when the cache is discarded + + [gtk] + -Fix: make sure menubar is always wide enough to expose all buttons (using a hidden invisible hbox of calculated size) + -Add: copy accel key menuitems from gschem and take over keyboard handling; hid_gtk now supports multi-key hotkeys + -Add: set tooltip on menu items + -Add: include all hotkeys in the tooltip for submenus + + [lesstif] + -Del: remove dumpkeys action/code: this info should be extracted from the lihata file + -Fix: there should be no global variable named 'n' in lesstif; make the stdarg thing a bit more robust and reusable + -Add: reenable code to set set menu font and color + + [core] + -Fix: draw_pad() used uninitialized pad color + -Add: SwitchHID action to change the HID module on the fly (works partially) + + [png] + -Fix: png max dpi should be 10k - modern printers easily do 2400 but some models are said to do 9600 DPI in one direction + + [gpmi] + -Fix: auto-copy .so files to src's plugin dir on compile so that running from source always has the latest .so files + + +pcb-rnd 1.0.9 +~~~~~~~~~~~~~ + [unglib] + -Fix: replace glib with minilibs in core and util/ + -Del: remove local dynamic string implementation in favor of genvector + -Move: vector.[ch] is used only by the autorouter, move it there + + [scconfig] + -Add: print warnings if glib is not found and selected components need to be left out + -Add: repeate some of the critical messages below the summary + -Fix: compiler warnings + -Fix: instead of two booleans, implement a 3-state "/controls" node with values disable, buildin, plugin for the plugins + -Change: better module summary printout at the end of ./configure + -Fix: use -fPIC on x86_64 to make sure plugins link + -Fix: gpmi plugin installation bugs + -Fix: src/plugin is cleaned on make clean + + [leak] + -API CHANGE: plugin init should return a pointer to the plugin uninit function + -Fix: a bunch of random memory leaks + -Fix: a bunch of potential buffer overruns + -Add: central infrastructure for uninit'ing GUI hids + -Fix: missing closedir() + -Add: uninit paste buffers + -Add: actions, flags and attributes are registered with a cookie so they an be deleted by cookie + -Fix: uninit plugins before hids so they have a chance to clean up registrations + -Fix: don't use dynamic strings where printing quoted string directly to a file would work + + [mods] + -Change: convert the ps and lpr exporters into configurable exporter plugins + -Rename: edif plugin to import_edif for consistency + -Change: move gcode and nelma from hid to plugin + -Move: gerber, bom and png to expoter plugins + -Cleanup: move old/unused/legacy functions to a new plugin called legacy_func + -Change: move fontmode to a separate plugin + + [core] + -Change: use a hash for flag storage - faster and simpler code + + [gpmi] + -Add: expotert hid callback for filled pad exporting + +pcb-rnd 1.0.8 +~~~~~~~~~~~~~ + [doc-rnd] + -Add: djopt examples + + [mods] + -Cleanup: split up action.c and spread the code in core and plugins + -Move: action pscalib() to the ps hid code + -Move: autoplace to a core plugin + -Move: autoroute to a core plugin + -Move: dbus to a defunct core plugin + -Move: djopt to a core plugin + -Move: edif to a core plugin + -Move: gpmi to a core plugin + -Move: import_sch to a core plugin + -Move: mincut to a core plugin + -Move: oldactions to a core plugin + -Move: puller to a core plugin + -Move: renumber to a core plugin + -Move: stroke to a core plugin + -Move: toporouter to a core plugin + -Move: vendordrill to a core plugin + + [ba] + -Add: when applying patches to the edited netlist, create missing nets + (new connections may implicitly define new nets) + -Fix: get the renumber action() fixed + -Fix: enable net(add,net,pin) action again and make it operate on the + edited netlist for the back annotation to take notes of the + changes made + + [libstroke] + -Add: menu in the gtk hid's res to toggle stroke enable + -Fix: osolete calls in libstroke action - libstroke support compiles now + -Fix: get the gtk gui call the central crosshair move event handler + instead of reproducing its code locally (... without libstroke) + + [util] + -Add: make clean + -Fix: compiler warnings, mostly unused vars in gsch2pcb + -Cleanup: indentation in gsch2pcb + + +pcb-rnd 1.0.7 +~~~~~~~~~~~~~ + -Cleanup: src/ should compile in c89 - no more // comments and variables declared in for() + -Cleanup: const correctness in src/ + -Cleanup: missing #includes in src/ + -Cleanup: unified, tab based indentation all over src/ + -Cleanup: move dmalloc include to central config.h + -Cleanup: move gts to src/3rd + -Cleanup: remove old/obsolete files inherited from the fork + -Cleanup: rename doc/ to doc-orig/ to avoid confusion and make it compile + -Fix: poly pin bounding box calculation adds clearance as rtree expects ([square]) + -Fix: loading default.pcb shouldn't override cursor pos and board sizes and shoudln't cause file date to be changed in the gui hids since it is loading a "misc" file + -Add: README in each main directory to explain what the directory is for + +pcb-rnd 1.0.6 +~~~~~~~~~~~~~ + [cycdrag] + -Add: "negative sized" selection selects anything that touches + -Add: cycle drag object action + + [scconfig] + -Fix: toporouter Makefile module adds its own action registration code, + so the central Makefile is independent of toporouter + -Add: --disable-toporouter + -Fix: use cc/cc for c compiler (so that it can be overridden) + -Fix: remove -std=gnu99: -std=c99 breaks with new gcc and -std is not + really portable + -Fix: include genht before glib.h because glib.h ruins inline + + [pinnum] + -Add: action and key binding for changing pin numbers in a footprint + + [gpmi] + -Fix: typo in hotkey name for manage plugins (reported by Bert Timmerman) + + [util] + -Fix: keylist: tolerate whitepsace in key sequences + -Fix: keylist resets locale to avoid broken table when gawk tries to + be too clever + + +pcb-rnd 1.0.5 +~~~~~~~~~~~~~ + [onpoint] + -Add: Robert Drehmel's on-point patch adapted for pcb-rnd + + [scconfig] + -Fix: properly configure and build and install even if there's space + in the source path (thanks to Jason White) + -Fix: take genht from the local copy, don't depend it being installed + +pcb-rnd 1.0.4 +~~~~~~~~~~~~~ + [ba] + -Add: back annotation + + [core] + -Fix: suppress no-font error message while loading default.pcb - the actual font is coming from the default font file + + [pcblib-param] + -Add: screw(), low level + -Fix: typo in the help of rcy() + + [mincut] + -Fix: solve debug works again + -Fix: make debug pngs during load optional + -Fix: don't use function-in-function - that's a gcc-specific feature + -Fix: don't use alloca(), use malloc() (C99) + -Add: Makefile to test against known refs + + [pcb-fp] + -Fix: gtk lib window tag print doesn't segfault if there are no tags for a footprint + -Del: local hash and library search implementation for footprint names in buffer.c - libpcb_fp should handle this + +pcb-rnd 1.0.3 +~~~~~~~~~~~~~ + [gpmi] + -Add: GPMI plugin/buildin for scripiting (import of project pcb-gpmi) + + [tostyle] + -Add: new feature to adjust the sizes of object(s) to the values of the current routing style + + [pcb-fp] + -Add: support for parsing and caching footprint tags (file elements) + -Add: the gtk HID displays tags + -Add: the gtk HID can filter for tags + + [pcblib-param] + -Add: bga() + -Add: generic qf() generator + -Add: qfn() - based on qf() + -Add: qfp() - based on qf() + -Add: plcc() - based on qf() + -Add: qsop() - based on so() + -Add: silkmark: accept multiple values + -Add: silkmark: can be external + -Add: silkmark: new styles exteranl45, dot, circle, and arc + -Add: connector() has a sequence option to change pin numbering + -Add: some tunings for connector sequence=zigzag to do something usable with etrunc=1 + + [hid] + -Add: dynamic menus: create_menu(), menu paths, runtime insertion of menus in core + -Add: dynamic menus in gtk + -Add: dynamic menus in lesstif + -Fix: more const correctness in dialog box code + + [scconfig] + -Add: ./configure --help + -Add: print configuration summary at the end + -Add: autodetect HOST (use sys/sysid) + -Add: src/3rd for central hosting of 3rd party software libs + -Add: support "buildins": plugins built into the code + -Change: move genht to src/3rd; policy: prefer genht over glib hash + -Fix: tests try to run pcb-rnd, not pcb + -Fix: central LDFLAGS and CFLAGS should contain the ldflags/cflags detected for generic use + + [pcb-mincut] + -Merge: pcb-mincut is imported in pcb-rnd, the extern repo will be removed + + [core] + -Add: event subsystem + -Add: gui_init event + -Add: generic plugin support: track plugins loaded, have a menu for managing them + -Add: more accessors to query unit details - for the gpmi scripts + -Add: pcb-printf %mI prints coordinate in internal coord format + -Add: calls for removing actions + -Add: calls for removing a hid (useful for removing exporter hids registered by scripts) + -Add: path resolution: support ~ in paths + -Add: real regex search and real string list search (in search by name actions) + -Change: switch over actions from bsearch() to a genht hash - simpler code, potentially also faster + -Fix: don't allow the registration of an action with a name that's already registered + + + [fp2anim] + -Add: optional dimension lines + -Add: more fine grained annotation control + -Change: switch over to vector fonts for better scaling + -Fix: draw rounded pads (new pad syntax only) + -Fix: make sure to generate sane arcs + + [doc-rnd] + -Add: official central key list + +pcb-rnd 1.0.2 +~~~~~~~~~~~~~ + [pcblib-param] + -Fix: central bool handling (connector() etrunc), values: on/off, true/false, 1/0 + -Fix: typo in so() parameter descriptions + -Fix: connector() typo in error() + -Add: more elaborate help syntax: easier to read with scripts + + [fp2anim] + -Fix: read multiline directives properly - a newline after each directive is still needed, tho + -Fix: allow whitepsace between directive name and opening bracket + -Fix: create all layers in advance - this fixes the case when the fp doesn't draw on some layers (the macro still exists) + -Fix: rline() is extended by width/2 if there are no rounding; it seems this how pcb defines lines + -Fix: leave extra margin in photo mode for the 3d edges + -Add: support for old-style pad() + -Add: support for Mark() (relocate the diamond) + -Add: options to turn off the grid and annotation - useful for thumbnails + + [scconfig] + -Fix: always have config.h, don't ifdef it + -Fix: glib is a core dependency that should be added even if the gtk hid is not used + -Fix: make clean removes pcb-rnd, not pcb (executable file name typo) + -Add: make clean in util/ + -Add: options to disable gd and/or jpeg or png or gif + -Add: be able to detect and configure lesstif + -Add: --disable-gtk and --disable-lesstif; --disable-xinerama and --disable-xrender for lesstif + -Add: use detected -rdynamic so that plugins can link against the executable + -Change: detect both gtk and lesstif as optional dependencies + -Cleanup: generate hidlist.h from tmpasm instead of shell to remove shell dependency + -Del: a bunch of obsolete #defines inherited from auto* + + [core] + -Add: --gui explicitly selects a gui hid + -Add: don't leave preferred order of GUIs to the chance, make it explicit + + +pcb-rnd 1.0.1 +~~~~~~~~~~~~~ + [core] + -Fix: don't read beyond the common part of the struct in IsPointInPad (since it's called for lines too, and those have much less fields) + -Fix: where stdarg is avaialble, also print messages to stderr - useful if things go wrong before a GUI is working + + [gtk] + -Fix: don't crash but write error message and exit if gpcb-menu.res is empty + + [square] + -Fix: 90 deg rotation rotates shape style + -Add: action.c and change.c code to get shaped vias + -Fix: don't change pin shape for square and octagon in rotation + + [mincut] + -Add: command line setting --enable-mincut (0 or 1) as mincut can be slow + it is a global disbale setting and make a local, per pcb setting + for enabling mincut; also add a per pcb setting/flag + -Fix: disable debug draw by default + -Fix: fall back to the old short warn method when mincut fails + -Fix: avoid segfaults by detecting broken graph early + -Workaround: if mincut sees a graph with multiple unconnected components, doesn't try to solve but falls back to randomly highlight something + + [intconn] + -Workaround: find intconn pads only on the same layer + + [nonetlist] + -Workaround: ignore nonetlist pads even if the flag is in the element name + + [scconfig] + -Add: scconfig/ - switch over from autotools to scconfig + + [pcblib] + -Cleanup: new, trimmed back pcblib/ with essential footprints only + + [pcblib-param] + -Add: new parametric footprints - no more m4-hardwiring, use your + preferred language! + -Add: acy(), alf(), rcy(), connector(), dip() + -Add: so(), tssop(), msop(), ssop() + + [pcb-fp] + -Add: central lib for footprint search and load in pcb and gsch2pcb + + [util] + -Add: gsch2pcb fork to support [nonetlist] and [pcblib-param] + + [fp2anim] + -Add: fp to animator script for fast preview + + [polygrid] + -Add: ps output: draw grid in polys instead of fill (doesn't fully work) + -Fix: set proper max value so the control is enabled + + + [debian] + -Update: build the package with scconfig and footprint changes + + +pcb-rnd 1.0.0 +~~~~~~~~~~~~~ + [square] -Add: initial implementation + [intconn] -Add: initial implementation + [nonetlist] -Add: initial implementation + [flagcomp] -Add: initial implementation + [mincut] -Add: initial implementation Index: tags/1.2.7/INSTALL =================================================================== --- tags/1.2.7/INSTALL (nonexistent) +++ tags/1.2.7/INSTALL (revision 13657) @@ -0,0 +1,69 @@ +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 + - motif or lesstif if you are using the lesstif frontend + - gdlib if you are using the png HID + +For developers: + - flex + - bison + Index: tags/1.2.7/Makefile =================================================================== --- tags/1.2.7/Makefile (nonexistent) +++ tags/1.2.7/Makefile (revision 13657) @@ -0,0 +1,52 @@ +all: FORCE + cd src_3rd/puplug/util && $(MAKE) + 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 + +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 + +FORCE: Index: tags/1.2.7/Makefile.conf.in =================================================================== --- tags/1.2.7/Makefile.conf.in (nonexistent) +++ tags/1.2.7/Makefile.conf.in (revision 13657) @@ -0,0 +1,20 @@ +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@/share/man/man1 +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@ +@] Index: tags/1.2.7/README =================================================================== --- tags/1.2.7/README (nonexistent) +++ tags/1.2.7/README (revision 13657) @@ -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: pcb-rnd (a) igor2.repo.hu + 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/1.2.7/Release_notes =================================================================== --- tags/1.2.7/Release_notes (nonexistent) +++ tags/1.2.7/Release_notes (revision 13657) @@ -0,0 +1,31 @@ +pcb-rnd 1.2.7 +~~~~~~~~~~~~~ + +The focus of the release is pad stacks: a new, generic object type that +can serve as: + - via + - pin + - pad + - mounting hole + +The second most important effort was fixing most of the remaining +subcircuit-related issues. By now subcircuits with padstacks or +with heavy terminals are production-quality alternatives to +elements/pins/pads. + +The arbitrary shaped pad support and polygon-clear-in-polygon +features are upgraded with thermals. It is now possible to generate +a thermal relief for any SMD or through-hole pad: + - round cap lines + - square cap lines + - circle + - arc + - arbitrary shaped convex polygon + +The attribute dialog API got extended by a Dynamic Attribute Dialog (DAD) API; +all new dialog boxes are implemented using the DAD, which makes the same code +work with all existing HIDs. Already existing, per-HID dialog implementions +will be revised and converted to DAD wherever possible. + +Plugin io_eagle is now mature enough to load complex boards drawn in +Eagle, using both the new xml format and the older binary format. Index: tags/1.2.7/config.h.in =================================================================== --- tags/1.2.7/config.h.in (nonexistent) +++ tags/1.2.7/config.h.in (revision 13657) @@ -0,0 +1,254 @@ +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#define PCB_INLINE static inline 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 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/* 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 `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 translation of program messages to the user's native language is requested. */\n} +print_ternary ?/local/pcb/want_nls {#define ENABLE_NLS 1} {/*#undef ENABLE_NLS */} + +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/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 [@ + +/* 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@" + + +/* 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 @/local/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 +# endif + +#endif + +#endif +@] Index: tags/1.2.7/configure =================================================================== --- tags/1.2.7/configure (nonexistent) +++ tags/1.2.7/configure (revision 13657) @@ -0,0 +1,4 @@ +#!/bin/sh +cd scconfig +make +./configure "$@" Property changes on: tags/1.2.7/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/data/Makefile =================================================================== --- tags/1.2.7/data/Makefile (nonexistent) +++ tags/1.2.7/data/Makefile (revision 13657) @@ -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/1.2.7/data/README =================================================================== --- tags/1.2.7/data/README (nonexistent) +++ tags/1.2.7/data/README (revision 13657) @@ -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/1.2.7/data/application-x-excellon-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-excellon-16.png =================================================================== --- tags/1.2.7/data/application-x-excellon-16.png (nonexistent) +++ tags/1.2.7/data/application-x-excellon-16.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-excellon-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-excellon-16.svg =================================================================== --- tags/1.2.7/data/application-x-excellon-16.svg (nonexistent) +++ tags/1.2.7/data/application-x-excellon-16.svg (revision 13657) @@ -0,0 +1,1271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-excellon-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-excellon-22.png =================================================================== --- tags/1.2.7/data/application-x-excellon-22.png (nonexistent) +++ tags/1.2.7/data/application-x-excellon-22.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-excellon-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-excellon-22.svg =================================================================== --- tags/1.2.7/data/application-x-excellon-22.svg (nonexistent) +++ tags/1.2.7/data/application-x-excellon-22.svg (revision 13657) @@ -0,0 +1,1571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-excellon-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-excellon-24.png =================================================================== --- tags/1.2.7/data/application-x-excellon-24.png (nonexistent) +++ tags/1.2.7/data/application-x-excellon-24.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-excellon-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-excellon-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-excellon-32.png =================================================================== --- tags/1.2.7/data/application-x-excellon-32.png (nonexistent) +++ tags/1.2.7/data/application-x-excellon-32.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-excellon-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-excellon-32.svg =================================================================== --- tags/1.2.7/data/application-x-excellon-32.svg (nonexistent) +++ tags/1.2.7/data/application-x-excellon-32.svg (revision 13657) @@ -0,0 +1,1406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-excellon-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-excellon-48.png =================================================================== --- tags/1.2.7/data/application-x-excellon-48.png (nonexistent) +++ tags/1.2.7/data/application-x-excellon-48.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-excellon-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-excellon-48.svg =================================================================== --- tags/1.2.7/data/application-x-excellon-48.svg (nonexistent) +++ tags/1.2.7/data/application-x-excellon-48.svg (revision 13657) @@ -0,0 +1,1283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-excellon.svg =================================================================== --- tags/1.2.7/data/application-x-excellon.svg (nonexistent) +++ tags/1.2.7/data/application-x-excellon.svg (revision 13657) @@ -0,0 +1,1289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-gerber-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-gerber-16.png =================================================================== --- tags/1.2.7/data/application-x-gerber-16.png (nonexistent) +++ tags/1.2.7/data/application-x-gerber-16.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-gerber-16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-gerber-16.svg =================================================================== --- tags/1.2.7/data/application-x-gerber-16.svg (nonexistent) +++ tags/1.2.7/data/application-x-gerber-16.svg (revision 13657) @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-gerber-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-gerber-22.png =================================================================== --- tags/1.2.7/data/application-x-gerber-22.png (nonexistent) +++ tags/1.2.7/data/application-x-gerber-22.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-gerber-22.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-gerber-22.svg =================================================================== --- tags/1.2.7/data/application-x-gerber-22.svg (nonexistent) +++ tags/1.2.7/data/application-x-gerber-22.svg (revision 13657) @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-gerber-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-gerber-24.png =================================================================== --- tags/1.2.7/data/application-x-gerber-24.png (nonexistent) +++ tags/1.2.7/data/application-x-gerber-24.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-gerber-24.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-gerber-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-gerber-32.png =================================================================== --- tags/1.2.7/data/application-x-gerber-32.png (nonexistent) +++ tags/1.2.7/data/application-x-gerber-32.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-gerber-32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-gerber-32.svg =================================================================== --- tags/1.2.7/data/application-x-gerber-32.svg (nonexistent) +++ tags/1.2.7/data/application-x-gerber-32.svg (revision 13657) @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-gerber-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-gerber-48.png =================================================================== --- tags/1.2.7/data/application-x-gerber-48.png (nonexistent) +++ tags/1.2.7/data/application-x-gerber-48.png (revision 13657) Property changes on: tags/1.2.7/data/application-x-gerber-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/application-x-gerber-48.svg =================================================================== --- tags/1.2.7/data/application-x-gerber-48.svg (nonexistent) +++ tags/1.2.7/data/application-x-gerber-48.svg (revision 13657) @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-gerber.svg =================================================================== --- tags/1.2.7/data/application-x-gerber.svg (nonexistent) +++ tags/1.2.7/data/application-x-gerber.svg (revision 13657) @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-footprint-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-footprint-16.png =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-16.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-16.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-footprint-16.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-16.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-16.svg (revision 13657) @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-footprint-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-footprint-22.png =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-22.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-22.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-footprint-22.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-22.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-22.svg (revision 13657) @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-footprint-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-footprint-24.png =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-24.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-24.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-footprint-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-footprint-32.png =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-32.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-32.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-footprint-32.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-32.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-32.svg (revision 13657) @@ -0,0 +1,2302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-footprint-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-footprint-48.png =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-48.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-48.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-footprint-48.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint-48.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint-48.svg (revision 13657) @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-footprint.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-footprint.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-footprint.svg (revision 13657) @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-layout-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-layout-16.png =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-16.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-16.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-layout-16.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-16.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-16.svg (revision 13657) @@ -0,0 +1,1333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-layout-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-layout-22.png =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-22.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-22.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-layout-22.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-22.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-22.svg (revision 13657) @@ -0,0 +1,1423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-layout-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-layout-24.png =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-24.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-24.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-layout-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-layout-32.png =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-32.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-32.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-layout-32.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-32.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-32.svg (revision 13657) @@ -0,0 +1,1362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-layout-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-layout-48.png =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-48.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-48.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-layout-48.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-layout-48.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout-48.svg (revision 13657) @@ -0,0 +1,1341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-layout.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-layout.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-layout.svg (revision 13657) @@ -0,0 +1,1346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-netlist-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-netlist-16.png =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-16.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-16.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-netlist-16.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-16.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-16.svg (revision 13657) @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-netlist-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-netlist-22.png =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-22.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-22.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-netlist-22.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-22.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-22.svg (revision 13657) @@ -0,0 +1,567 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-netlist-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-netlist-24.png =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-24.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-24.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-netlist-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-netlist-32.png =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-32.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-32.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-netlist-32.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-32.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-32.svg (revision 13657) @@ -0,0 +1,1310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-netlist-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/application-x-pcb-netlist-48.png =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-48.png (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-48.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/data/application-x-pcb-netlist-48.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist-48.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist-48.svg (revision 13657) @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/application-x-pcb-netlist.svg =================================================================== --- tags/1.2.7/data/application-x-pcb-netlist.svg (nonexistent) +++ tags/1.2.7/data/application-x-pcb-netlist.svg (revision 13657) @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/icon-theme-installer =================================================================== --- tags/1.2.7/data/icon-theme-installer (nonexistent) +++ tags/1.2.7/data/icon-theme-installer (revision 13657) @@ -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/1.2.7/data/icon-theme-installer ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/data/pcb-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/pcb-48.png =================================================================== --- tags/1.2.7/data/pcb-48.png (nonexistent) +++ tags/1.2.7/data/pcb-48.png (revision 13657) Property changes on: tags/1.2.7/data/pcb-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/pcb.desktop =================================================================== --- tags/1.2.7/data/pcb.desktop (nonexistent) +++ tags/1.2.7/data/pcb.desktop (revision 13657) @@ -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/1.2.7/data/pcb.svg =================================================================== --- tags/1.2.7/data/pcb.svg (nonexistent) +++ tags/1.2.7/data/pcb.svg (revision 13657) @@ -0,0 +1,1070 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Lapo Calamandrei + + + + Text editor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.7/data/pcb.xml =================================================================== --- tags/1.2.7/data/pcb.xml (nonexistent) +++ tags/1.2.7/data/pcb.xml (revision 13657) @@ -0,0 +1,40 @@ + + + + + PCB layout + + + + + + + + PCB footprint + + + + + + + + PCB netlist + + + + + Gerber file + + + + + + + + Excellon drill file + + + + + + Index: tags/1.2.7/data/pcb_icon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/data/pcb_icon.ico =================================================================== --- tags/1.2.7/data/pcb_icon.ico (nonexistent) +++ tags/1.2.7/data/pcb_icon.ico (revision 13657) Property changes on: tags/1.2.7/data/pcb_icon.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/data/regen_files =================================================================== --- tags/1.2.7/data/regen_files (nonexistent) +++ tags/1.2.7/data/regen_files (revision 13657) @@ -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/1.2.7/data/regen_files ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/data/x-excellon.desktop =================================================================== --- tags/1.2.7/data/x-excellon.desktop (nonexistent) +++ tags/1.2.7/data/x-excellon.desktop (revision 13657) @@ -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/1.2.7/data/x-gerber.desktop =================================================================== --- tags/1.2.7/data/x-gerber.desktop (nonexistent) +++ tags/1.2.7/data/x-gerber.desktop (revision 13657) @@ -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/1.2.7/data/x-pcb-footprint.desktop =================================================================== --- tags/1.2.7/data/x-pcb-footprint.desktop (nonexistent) +++ tags/1.2.7/data/x-pcb-footprint.desktop (revision 13657) @@ -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/1.2.7/data/x-pcb-layout.desktop =================================================================== --- tags/1.2.7/data/x-pcb-layout.desktop (nonexistent) +++ tags/1.2.7/data/x-pcb-layout.desktop (revision 13657) @@ -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/1.2.7/data/x-pcb-netlist.desktop =================================================================== --- tags/1.2.7/data/x-pcb-netlist.desktop (nonexistent) +++ tags/1.2.7/data/x-pcb-netlist.desktop (revision 13657) @@ -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/1.2.7/doc/Autostyle.html =================================================================== --- tags/1.2.7/doc/Autostyle.html (nonexistent) +++ tags/1.2.7/doc/Autostyle.html (revision 13657) @@ -0,0 +1,16 @@ + + + + + + + +
Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ Index: tags/1.2.7/doc/Autostyle.sh =================================================================== --- tags/1.2.7/doc/Autostyle.sh (nonexistent) +++ tags/1.2.7/doc/Autostyle.sh (revision 13657) @@ -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/1.2.7/doc/Autostyle.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/Makefile =================================================================== --- tags/1.2.7/doc/Makefile (nonexistent) +++ tags/1.2.7/doc/Makefile (revision 13657) @@ -0,0 +1,29 @@ +MENU_RES=../src/pcb-menu-gtk.lht ../src/pcb-menu-lesstif.lht +MENU_RES_MKEY=../src/pcb-menu-mkey.lht +KEYLIST=../util/keylist.sh +DEBLIST=../util/devhelpers/deblist.sh + +all: keys.html keys_mkey.html features/debian_list.html + ROOT="" ./Autostyle.sh *.html + ROOT="../" ./Autostyle.sh features/*.html + +keys.html: $(MENU_RES) $(KEYLIST) + $(KEYLIST) $(MENU_RES) > keys.html + +keys_mkey.html: $(MENU_RES_MKEY) $(KEYLIST) + $(KEYLIST) $(MENU_RES_MKEY) > keys_mkey.html + +install: + cd man && $(MAKE) install + +linstall: + cd man && $(MAKE) linstall + +uninstall: + cd man && $(MAKE) uninstall + +clean: + cd man && $(MAKE) clean + +distclean: + cd man && $(MAKE) distclean Index: tags/1.2.7/doc/README =================================================================== --- tags/1.2.7/doc/README (nonexistent) +++ tags/1.2.7/doc/README (revision 13657) @@ -0,0 +1,11 @@ +pcb-rnd documentation: work in progress. + +Most notable subdirectories: + developer/ documentation for developers + user/ user reference manual + features/ details of pcb-rnd features + conf/ documentation of the configuration system + devlog/ random thoughts and articles + man/ UNIX manual pages + resources/ logos, screenshots, artwork + Index: tags/1.2.7/doc/TODO =================================================================== --- tags/1.2.7/doc/TODO (nonexistent) +++ tags/1.2.7/doc/TODO (revision 13657) @@ -0,0 +1,275 @@ +1. For the upcoming release =============================================================================== ++ BUG: shape editor dialog: catch layer change and regen the shape [report: SQ6POG] ++ BUG: missing subc snap: + + polygon pad center snap [report: jg] + + subc centroid/origin snap [report: jg] + +2. For later releases =============================================================================== +- 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 +- BUG: lesstif layer selector doesn't work on silk and mask and paste (composite layers) [report: karl] +- BUG: lesstif: invalidate_all() on config change colors [report: karl] +- doc: explain the library path in 03_data [report: karl] +- buffer: break up padstack, just like breaking up subcircuits +- BUG: subc/term: + - term netlist connectivity (r10843): + + autoplace.c - needs intensive testing (including per perturbation operation tests) + - autoroute.c:961 + - autoroute.c:1000 +- BUG: can't rotate polygon [report: sam] +- BUG: parametric footprint dialog: do not regen the footprint while the user is editing - revise the timer code [report: sam] +- BUG: subc terminals should be drawn at the end [report: Ade] +- BUG: DRC hilight (select+find) broke: only find shows, clicking the next bug doesn't clear the flags of the previous +- BUG: DRC preview windows don't show anything if generated after shift-tab flip (maybe with tab too?) +- BUG: when DRC sizes are saved in user conf, they are overridden from the default.pcb -> should be fixed by removing these from pcb_board_t [report: Alain] + Reason: pcb_board_t Bloat, Shrink, minWid, minSlk, minDrill, minRing -> remove them, use values from the config system instead +- 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 +- BUG: advanced search doesn't deal with subc parts; do this after element removal using the new rtree loops? +- BUGS: parametric footprint dialog [report: Alain] ; Select a parametric footprint : + ? [gtk2] it launches a new dialog. Cancel this dialog and try to open it again : no new dialog window. You have to select another line in the tree menu, then come back to the wanted line, to open the dialog again. + - Igor2 can't reproduce this + - [gtk3] cancel do not close the dialog(s). In fact 2 dialog windows are created, and message : GLib-CRITICAL **: g_source_remove: assertion 'tag > 0' failed : pops up. +- BUG: GTK: "Edit->Edit attributes of->layout" dialog does not close with WM decoration [report:celem] + - This dialog needs a scrolled window. => extend the attribute dialog both in gtk and lesstif to make scrollable window and rewrite this dialog using DAD, in the dialogs plugin + - Lesstif HID does not have this dialog => implement it, using DAD + - Default keyboard focus on "OK" button ? (allow closing the dialog with keyboard) +- 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] +- vendor: be able to load multiple vendor files (project spec for skips, central for vendor) [report: celem] +- feature: property editor should deal with flags +- subc feature: figure how to do in-place edition of subc, e.g. moving refdes text +- feautres/cleanup: hid: + - "erase" color: + - pcb_pad_clear_callback() -> hopefully drawn on negative mask only (check this) + - holes_after should be set to 1 everywhere, then removed -> breaks gerber + - holes should be drawn below silk and mask (maybe this could be a config setting) +- feature: fp_wget cache dir configurable [report: agaran] +- feature in subc/term: + - new terminal attribute: "do not connect to the same subc copper" (agaran's coil example) ++ feature req: show grid in both mm and mil in the status bar [report:smilie] +- update /usr/share/pcb-rnd/default.pcb to default lihata + - after switch, update doc/conf and doc/user references to conf settings from .pcb to .lht as needed +- HID: option for using a fixed background color for the preview widget renders; using the user configured one goes wrong when it's set to dark [report: Alain] +- Rubberband Arcs: + - BUG: Moving arc endpoints in rubberband mode doesn't move connected lines correctly so they become detached. [Fixing:Ade] + - BUG: Rubberband move line endpoints ignores connected arc endpoints. [Fixing:Ade] +- fontsel: ttf import? +- library window: allow long tags and long location text to split +- undo on new layer from right-click menu in gtk layersel doesn't work +- GTK layers [report: Ade]: + - BUG: move the layer+selected color change from the preferences menu to the layer popup (but this should probably live in gui-config.h) +- gtk layersel feature requests: + - consider to provide a config setting for making open-group-name horizontal [report: istankovic] +- layer rewrite: + - catch the layer change signal from polygons and reclip; Evan's test case: + draw a line on a layer and a poly on another and change whether they are in + the same layer group + - Layer group changes are not marked in the title bar; Evan's test case: + make any change in the layer group screen, return to the main screen, no * will be added in the title bar in front of the file name. +- GTK Preferences->User PoV->Layers : Hit 'v' to "zoom fit" the preview [report: Alain] + - allow GTK to handle keys in preview + - use the zoompan engine for the zooming. Modifiy API if necessary +- check gpmi when pcb-rnd is fully linstalled - broken symlinks? +- multi-key: display state on the gui +- cleanup/rewrite resources: + - load/swap menus (TODO#1) + - gpmi: + - hid: hid_destroy (pair of hid_create) + - cleanup on unload: remove menus +- conf: + - remove CFN_INCREMENTS, test if saving increments from preferences works + - config pov: change prio + - gtk preferences: check what takes 131 megs of VIRT ram (on top); destroy the dialog structures when closed + - gtk preferences: poly isle area widget missing from the sizes tab + - BUG: default layer names from the user config are ignored + - fp_fs_search: kill anything that gets ':' separated string as path list, get a config list instead + - switch the lesstif HID over from attribs to conf + - remove redundancy: don't store values in the PCB struct that are in the design conf + - increments are not really implemented +- 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 + - grid size change should be undoable? [report:Evan] + - maybe other conf settings too? +- pcb_act_Attributes -> this could be handled by the property editor maybe? but what about layout attributes and the lesstif hid? +- layer group rewrite: + - remove PCB_MAX_LAYERGRP and PCB_MAX_LAYER and make them dynamic + - make the color config dynamic too; invent color for new layers +- layer groups from config (e.g. CLI) is ignored +- layer rewrite: central menu buttons + - lesstif needs to remember the widgets via lb->w in menu.c + - rewrite the central code for callbacks? +- io_pcb: new, optional "layer tag" field in mainline's file format +- extend the DRC window to be a generic location list (or rather rewrite with DAD!) + - buttons to select one or all items or all items including locked + - io infra for save incompatibility note with DRC list + - import sch. shouldn't select elements to be removed but put them on a drc list + - display number of items at top of drc window + - export to file +- biggish revamp of the export menu. The whole GUI is clearly designed for the case of only a very few exporters and we now have a lot. + - unify how output files are accessed/checked: confirmation on overwrite +- fp_board: extend the API so that the element can be presented without saving to a file +- cleanup: remove mnemonic from the menu system + - check the central code and struct fields + - remove "m=" fields from the menu lihata files +- SUBC missing features: + - manual layer binding (reuse csect?) +- core lib splitup: + - gsch2pcb: generalize plugin/buildin loading for external tools, check if gsch2pcb can work from plugins +- res/menu: + - search for vendor in the hid plugins, there should be no trace of it (vendor should register its in submenus with anchors) + - re-add dynamic menus after a gui change: + - either remember dynamic menus in a separate list so they can be rebuilt + - or provide hooks and let plugins deal with it + - gpmi: auto-remove menus by cookie (TODO#2) + - 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 +- 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" +- reduce + - export_bom: rewrite the string list code using htsp and/or lists + - hash in hid_attrib.c? + - nelma and gcode both invent .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 + - mods: + - gpmi (and other buildins/plugins) not showing up in the about box +- self contained + - dialog box to print where the actual files are coming from, including if the font came from embedded/internal (gui version of --show-paths) + - project specific menus from extra lihata files - maybe from project.lht +- vendor drill plugin: + - check if we want to keep vendor name +- dir rename trunk/pcblib/tru-hole should handle make correctly and not walk on existing web services or user installs +- 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 +- query & advanced search + - search expr wizard should pick up the expression from the button when clicked + - field accessors: + - pad area + - pin area + - line (and pad) length and length^2 + - 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 +- feature plugins: + - autocrop doesnt undo (new layout, add some -maskmanaul content, autocrop(), & undo: gui view shifts, board size unchanged [report: Miloh] + - distalign doesn't work with subc ( align() and distribute()) [report:Miloh] + - distalign pcb_crosshair option doesn't work as a reference point [report:Miloh] + - can't undo after boardflip(), (ERROR: Attempt to pcb_undo() with Serial == 0) [report:Miloh] + +3. Long term =============================================================================== + +SUBC: element removal: + - cleanup: remove the parallel PCB_TYPE_* enum and maybe all the type/ptr1/ptr2/ptr3 mess too + - remove Line->Number and *->Number: we use ->term + +GTK2: + - next_gui: keep them open, hide + +GTK3: + + overlapping objects (e.g. 2 fat lines crossing on silk) are darker on the overlap; we need uniform color + + mouse scroll wheel doesn't work in cross section + - zoom hangs: press 'z' on the drawing area -> hang + + xor draw fails after 'i' library footprint placement; in fail mode there's no xor outline of buffer; drawing a line fixes it + - elliptic arc rendering + - layer selector vertical layer group name truncation + - main window resize scroll bar warnings + - component draw "flicker", depending on pan: http://igor2.repo.hu/tmp/gtk3_bug1a.jpg http://igor2.repo.hu/tmp/gtk3_bug1a.jpg + - missing grid points: http://igor2.repo.hu/tmp/gtk3_bug2.png + +Eagle binary: + - padstack clearances for element pins will rely on connectivity to other polygons layer by layer defined in the netlist + - need to refine naming of library (.lbr) elements in loaded .lbr files + - need to add support for non top silk (tPlace), tDocu and top copper text in read.c + - 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. + +CLEANUP #7: the big object split +- remove pcb_obj_type_t from const.h - use obj_any.h instead + + +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 =============================================================================== +- BUG: main.c: SIGPIPE - detect it (needed for popen) +- advanced grid settings: + - keep two lists of preferred grid sizes, one in mil, one in mm + - generate the grid selection menu from those lists + - action to step up and down among those predefined grid sizes + - make sure it is possible to edit the lists in preferences +- libstroke: zoom +- improve locking: + - consider a move-only lock + - when thermal and some other operations are applied on a locked element, indicate it +- Erich's gtk lag report: press 's' a lot then move the mouse - 's' ends up in the new loc! +- the TAB bug: (over ssh -X) press tab for a good 15 seconds; release; it won't work again for a fraction of a second +- 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] +- bug: redrawbug1: grap c1, the diagonal trace gets drawn over U1's silk - it's redrawn because of the overlapping bounding box with C1, while U1 has no overlap [report:Evan] +- bug: draw overlapping lines, a short fully under a long; click on the short, it gets selected but it's not visible because the long hides it [report:Evan] +- bug: layer menu: the bottom silk screen icon color changes from gray-black to brown when any layer is selected. [report:Evan] +- GTK "save as" dialog: there should be an "auto" or "guess by extension" option in the save dialog format +- 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 +- missing rotate polygon (mainline too) +- zoom in too deep onto board edge and the implicit outline rectangle behaves strangely [report:Evan] +- scconfig: check if it picks up settings from env vars (for a gentoo build) +- replace mkdtemp() with something safer +- display net names on pins, vias (and maybe tracks?) when zoomed in enough +- DRC should warn for thin poly hair +- rotate shaped vias don't rotate the shape (is via rotated at all?) +- new examples + - blinking led with parametric footprints + - example of nonetlist: 1206 jumpers and logos +- decide what to do with old doc - texi doesn't seem to work at all +- In-line help needs update/re-structuration + - +- rethink/rewrite the action/change infrastructure - too many void *ptr1 + pointers, too many code duplication +- double sided board, poly on both layers; grab existing lines on one layer and + move then around. If all layers are visible, redraw of the far side layer + is slow and causes flickering elements from that layer until the front is + redrawn. Maybe we should have less flushes? +- gpmi: + - dialog: attribute dialog: mini parser from text + - fix debug draw in the gtk hid + - ACTE_action(): coords should not be int but Coord + - get timers to work +- dmalloc: #include from the bottom from each file. Is this a good idea?! +- win32 port {large} + - clean up central Makefile.in rules: + - remove cat, sed, grep where possible, use scconfig instead +- 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 + 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 +- while drawing a line, the temporary outline should reflect the layer color +- push&shove + - keep 45-deg knee when grabbing a point for drag&drop in non-all-dir +- --dump-actions shows gpmi paths ( is this related? it looks unexpected to me) +- unify gui invocation options: pcb-rnd --help gtk_[gdk|gl] and pcb-rnd --help lesstif both show and use different input methods [report:miloh] +- consider allowing negative Delta to be specified in CTRL-E property inspector +- consider a simple all in one function to create a default layer stackup for static/predictable layer formats being imported, to simplify importer coding +- 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 +- miter bug; miter crosses SMT pads under certain conditions [report: celem/miloh] Index: tags/1.2.7/doc/TODO.cleanup =================================================================== --- tags/1.2.7/doc/TODO.cleanup (nonexistent) +++ tags/1.2.7/doc/TODO.cleanup (revision 13657) @@ -0,0 +1,12 @@ +- rename: + - Note + - GetObjectBoundingBox + - XORDraw* + - conf_* +- centralize pcb_gui->attribute_dialog() +- replace return (*) with return * +- remove pcb board Zoom/x/y, move the drc stuff to config +- remove obsolete APIs: + pcb_board_get_filename(void); + pcb_board_get_name(void); + get_unit_list() Index: tags/1.2.7/doc/TODO.user =================================================================== --- tags/1.2.7/doc/TODO.user (nonexistent) +++ tags/1.2.7/doc/TODO.user (revision 13657) @@ -0,0 +1,10 @@ +- TEST: + - route style vs. autorouter + - smartdisperse + - compare to 1.2.4; term changes + - test subcircuits + - autoplace (compare to 1.2.4; term changes) + - autoroute (compare to 1.2.4; term changes) + - pcb_pstk_shape_hole_break(): min ring DRC rules on padstack, especially with asymmetric (non-centered) shapes + - test advanced search with padstacks + - query on subc Index: tags/1.2.7/doc/UNIX.txt =================================================================== --- tags/1.2.7/doc/UNIX.txt (nonexistent) +++ tags/1.2.7/doc/UNIX.txt (revision 13657) @@ -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/1.2.7/doc/conf/groups.html =================================================================== --- tags/1.2.7/doc/conf/groups.html (nonexistent) +++ tags/1.2.7/doc/conf/groups.html (revision 13657) @@ -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 .pcb 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/1.2.7/doc/conf/index.html =================================================================== --- tags/1.2.7/doc/conf/index.html (nonexistent) +++ tags/1.2.7/doc/conf/index.html (revision 13657) @@ -0,0 +1,97 @@ + + + + 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 .pcb 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. + + +

Compatibility with mainline

+ +None. The new configuration system uses a new logical structure, new file +format, new locations on the file system. Most setting names are the same +or very similar to the old ones. Some settings are renamed for clarity: +clearance is always called clearance, on the UI, in the code and in +config files as well (mainline pcb sometimes call it keepaway).The new, +tree-based logics adds a twist too: full names of settings are paths. + +

+ +Since configuration is stored in new files, pcb-rnd settings do not interfere +with pcb settings on any level. + + + Index: tags/1.2.7/doc/conf/index_prog.html =================================================================== --- tags/1.2.7/doc/conf/index_prog.html (nonexistent) +++ tags/1.2.7/doc/conf/index_prog.html (revision 13657) @@ -0,0 +1,14 @@ + + + + pcb-rnd - config programmer's index + + + +

The new config system in pcb-rnd

+

Programmer's documentation

+ +TODO + + + Index: tags/1.2.7/doc/conf/index_user.html =================================================================== --- tags/1.2.7/doc/conf/index_user.html (nonexistent) +++ tags/1.2.7/doc/conf/index_user.html (revision 13657) @@ -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 .pcb 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/1.2.7/doc/conf/lists.html =================================================================== --- tags/1.2.7/doc/conf/lists.html (nonexistent) +++ tags/1.2.7/doc/conf/lists.html (revision 13657) @@ -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/1.2.7/doc/conf/merging.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/conf/merging.png =================================================================== --- tags/1.2.7/doc/conf/merging.png (nonexistent) +++ tags/1.2.7/doc/conf/merging.png (revision 13657) Property changes on: tags/1.2.7/doc/conf/merging.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/conf/noextend.html =================================================================== --- tags/1.2.7/doc/conf/noextend.html (nonexistent) +++ tags/1.2.7/doc/conf/noextend.html (revision 13657) @@ -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 is 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/1.2.7/doc/conf/plugin_chk.html =================================================================== --- tags/1.2.7/doc/conf/plugin_chk.html (nonexistent) +++ tags/1.2.7/doc/conf/plugin_chk.html (revision 13657) @@ -0,0 +1,14 @@ + + + + pcb-rnd - config plugin checklist + + + +

The new config system in pcb-rnd

+

Plugin programmer's checklist

+ +TODO + + + Index: tags/1.2.7/doc/conf/prio.html =================================================================== --- tags/1.2.7/doc/conf/prio.html (nonexistent) +++ tags/1.2.7/doc/conf/prio.html (revision 13657) @@ -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/1.2.7/doc/conf/scalars.html =================================================================== --- tags/1.2.7/doc/conf/scalars.html (nonexistent) +++ tags/1.2.7/doc/conf/scalars.html (revision 13657) @@ -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/1.2.7/doc/conf/sources.html =================================================================== --- tags/1.2.7/doc/conf/sources.html (nonexistent) +++ tags/1.2.7/doc/conf/sources.html (revision 13657) @@ -0,0 +1,78 @@ + + + + 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.pcb + 300 + /usr/share/pcb-rnd/default.pcb + deprecated + 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 design (.pcb) files + +
design + 700 + saved in the design (.pcb) 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") + + + Index: tags/1.2.7/doc/conf/src/Makefile =================================================================== --- tags/1.2.7/doc/conf/src/Makefile (nonexistent) +++ tags/1.2.7/doc/conf/src/Makefile (revision 13657) @@ -0,0 +1,2 @@ +../merging.png: merging.dot + dot -Tpng merging.dot > ../merging.png \ No newline at end of file Index: tags/1.2.7/doc/conf/src/merging.dot =================================================================== --- tags/1.2.7/doc/conf/src/merging.dot (nonexistent) +++ tags/1.2.7/doc/conf/src/merging.dot (revision 13657) @@ -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/1.2.7/doc/conf/syntax.html =================================================================== --- tags/1.2.7/doc/conf/syntax.html (nonexistent) +++ tags/1.2.7/doc/conf/syntax.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_BOOLEAN.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_BOOLEAN.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_BOOLEAN.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_COLOR.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_COLOR.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_COLOR.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_COORD.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_COORD.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_COORD.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_INCREMENTS.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_INCREMENTS.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_INCREMENTS.html (revision 13657) @@ -0,0 +1,8 @@ + + +

pcb-rnd conf tree

+

type: increments

+A collection of coordinates representing an increment configuration. +

+TODO + Index: tags/1.2.7/doc/conf/tree/CFN_INTEGER.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_INTEGER.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_INTEGER.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_LIST.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_LIST.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_LIST.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_REAL.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_REAL.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_REAL.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/CFN_STRING.html =================================================================== --- tags/1.2.7/doc/conf/tree/CFN_STRING.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/CFN_STRING.html (revision 13657) @@ -0,0 +1,13 @@ + + +

pcb-rnd conf tree

+

type: string

+Text value. +

+Example values: +

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

pcb-rnd conf tree

+

type: unit

+Name of a unit. +

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

pcb-rnd conf tree

+

subtree: appearance

+ +
node name type flags description +
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 +
Index: tags/1.2.7/doc/conf/tree/appearance_color.html =================================================================== --- tags/1.2.7/doc/conf/tree/appearance_color.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/appearance_color.html (revision 13657) @@ -0,0 +1,35 @@ + +

pcb-rnd conf tree

+

subtree: appearance/color

+ +
node name type flags description +
black color 0 +
white color 0 +
background color 0 background and cursor color ... +
crosshair color 0 different object colors +
cross color 0 +
via color 0 +
via_selected color 0 +
pin color 0 +
pin_selected color 0 +
pin_name color 0 +
element color 0 +
element_nonetlist color 0 +
subc color 0 +
subc_selected color 0 +
subc_nonetlist color 0 +
padstackmark color 0 color of the center mark cross for padstacks +
rat color 0 +
invisible_objects color 0 +
invisible_mark color 0 +
element_selected color 0 +
rat_selected color 0 +
connected color 0 +
off_limit color 0 +
grid color 0 +
layer color 0 +
layer_selected color 0 +
warn color 0 +
mask color 0 +
paste color 0 +
Index: tags/1.2.7/doc/conf/tree/appearance_loglevels.html =================================================================== --- tags/1.2.7/doc/conf/tree/appearance_loglevels.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/appearance_loglevels.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/appearance_messages.html =================================================================== --- tags/1.2.7/doc/conf/tree/appearance_messages.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/appearance_messages.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/appearance_misc.html =================================================================== --- tags/1.2.7/doc/conf/tree/appearance_misc.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/appearance_misc.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/appearance_pinout.html =================================================================== --- tags/1.2.7/doc/conf/tree/appearance_pinout.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/appearance_pinout.html (revision 13657) @@ -0,0 +1,12 @@ + +

pcb-rnd conf tree

+

subtree: appearance/pinout

+ +
node name type flags description +
name_length integer 0 +
zoom real 0 +
offset_x coord 0 X offset of origin +
offset_y coord 0 Y offset of origin +
text_offset_x coord 0 X offset of text from pin center +
text_offset_y coord 0 Y offset of text from pin center +
Index: tags/1.2.7/doc/conf/tree/design.html =================================================================== --- tags/1.2.7/doc/conf/tree/design.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/design.html (revision 13657) @@ -0,0 +1,28 @@ + +

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 +
max_width coord 0 +
max_height coord 0 +
alignment_distance coord 0 default drc size +
bloat coord 0 default drc size +
shrink coord 0 +
min_wid coord 0 +
min_slk coord 0 +
min_drill coord 0 +
min_ring coord 0 +
text_scale integer 0 text scaling in % +
text_font_id integer 0 +
poly_isle_area real 0 polygon min area +
default_layer_name string 0 +
fab_author string 0 Full name of author for FAB drawings +
initial_layer_stack string 0 deprecated. +
groups string 0 string with layergroups +
routes string 0 string with route styles +
paste_adjust coord 0 Adjust paste thickness +
Index: tags/1.2.7/doc/conf/tree/editor.html =================================================================== --- tags/1.2.7/doc/conf/tree/editor.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/editor.html (revision 13657) @@ -0,0 +1,54 @@ + +

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 +
increments_mm increments 0 increments (size deltas) when drawing in mil +
increments_mil increments 0 increments (size deltas) when drawing in mil +
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 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 snp 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. +
show_number boolean 0 pinout shows number +
orthogonal_moves boolean 0 move items orthogonally. +
reset_after_element boolean 0 reset connections after each element while saving all connections +
auto_place boolean 0 flag which says we should force placement of the windows on startup +
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. +
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, element names are not drawn. +
description boolean 0 display element description as element name, instead of value +
name_on_pcb boolean 0 display Reference Designator as element name, instead of value +
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. +
route_radius real 0 temporary: route draw helper's arc radius at corners (factor of the trace thickness) +
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 +
Index: tags/1.2.7/doc/conf/tree/editor_selection.html =================================================================== --- tags/1.2.7/doc/conf/tree/editor_selection.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/editor_selection.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/editor_view.html =================================================================== --- tags/1.2.7/doc/conf/tree/editor_view.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/editor_view.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/rc.html =================================================================== --- tags/1.2.7/doc/conf/tree/rc.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/rc.html (revision 13657) @@ -0,0 +1,31 @@ + +

pcb-rnd conf tree

+

subtree: rc

+ +
node name type flags description +
verbose integer 0 +
quiet integer 0 print only errors on stderr +
backup_interval integer 0 time between two backups in seconds; 0 means disabled (no backups) +
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 +
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 anonymous .pcb files; optional fields: %P --> pid +
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 +
have_regex boolean 0 whether we have regex compiled in +
Index: tags/1.2.7/doc/conf/tree/rc_path.html =================================================================== --- tags/1.2.7/doc/conf/tree/rc_path.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/rc_path.html (revision 13657) @@ -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/1.2.7/doc/conf/tree/temp.html =================================================================== --- tags/1.2.7/doc/conf/tree/temp.html (nonexistent) +++ tags/1.2.7/doc/conf/tree/temp.html (revision 13657) @@ -0,0 +1,7 @@ + +

pcb-rnd conf tree

+

subtree: temp

+ +
node name type flags description +
rat_warn boolean 0 rats nest has set warnings +
Index: tags/1.2.7/doc/contrib.html =================================================================== --- tags/1.2.7/doc/contrib.html (nonexistent) +++ tags/1.2.7/doc/contrib.html (revision 13657) @@ -0,0 +1,70 @@ + + + + + pcb-rnd - contribution + + + + + + + + + +
Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

pcb-rnd - contribution

+ +If you are interested to help out, please contact me using + the live chat (CET daytime) or mail to: +pcb-rnd (at) igor2.repo.hu. + +

Contributing as a user

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

+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/1.2.7/doc/datasheet.html =================================================================== --- tags/1.2.7/doc/datasheet.html (nonexistent) +++ tags/1.2.7/doc/datasheet.html (revision 13657) @@ -0,0 +1,80 @@ + + + + pcb-rnd - datasheet + + + + + + + + + + +
Main + News + Doc + 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 +
board file formats + lihata (native), geda/PCB's .pcb, KiCad's s-expr kicad_pcb +
other native formats + geda/PCB's .fp for footprints (native) +
import formats + gEDA/gaf sch, gEDA/gaf netlist, dsn, edif +
export formats + gerber, png, ps, svg, bom, xy, bboard, dsn, gcode, ipcd356, lpr, nelma, kicad old pcb format +
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 (gedasymbols.org) +
scripting + embedded scripting using libgpmi (awk, python, lua, tcl, ruby, perl, php, scheme, lisp) +
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 +
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 +
+

+More details on some of the features, especially compared to gEDA/PCB. + + + Index: tags/1.2.7/doc/developer/alien_formats/hyp.txt =================================================================== --- tags/1.2.7/doc/developer/alien_formats/hyp.txt (nonexistent) +++ tags/1.2.7/doc/developer/alien_formats/hyp.txt (revision 13657) @@ -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/1.2.7/doc/developer/bisect.txt =================================================================== --- tags/1.2.7/doc/developer/bisect.txt (nonexistent) +++ tags/1.2.7/doc/developer/bisect.txt (revision 13657) @@ -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/1.2.7/doc/developer/blog_queue.txt =================================================================== --- tags/1.2.7/doc/developer/blog_queue.txt (nonexistent) +++ tags/1.2.7/doc/developer/blog_queue.txt (revision 13657) @@ -0,0 +1,14 @@ +Ready to blog: + +less urgent, almost finished: +- braille font +- unicode bdf bitmap dot matrix glyph insertion +- eeschema import (needs testing?) + +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/1.2.7/doc/developer/bridges/index.html =================================================================== --- tags/1.2.7/doc/developer/bridges/index.html (nonexistent) +++ tags/1.2.7/doc/developer/bridges/index.html (revision 13657) @@ -0,0 +1,11 @@ + + + + pcb-rnd developer manual + + + +This document has been moved to the +user doc. + + Index: tags/1.2.7/doc/developer/bugreport.html =================================================================== --- tags/1.2.7/doc/developer/bugreport.html (nonexistent) +++ tags/1.2.7/doc/developer/bugreport.html (revision 13657) @@ -0,0 +1,136 @@ + + + + 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 + +
+ 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/1.2.7/doc/developer/c89.html =================================================================== --- tags/1.2.7/doc/developer/c89.html (nonexistent) +++ tags/1.2.7/doc/developer/c89.html (revision 13657) @@ -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/1.2.7/doc/developer/data.html =================================================================== --- tags/1.2.7/doc/developer/data.html (nonexistent) +++ tags/1.2.7/doc/developer/data.html (revision 13657) @@ -0,0 +1,135 @@ + + + +

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 (e.g. lines, arcs, polygons) +
  • global objects (e.g. elements, subcircuits, vias) +
  • temporary logical connections (rat lines) +
+

+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: +

    +
  • top (component) side +
  • bottom (solder) side +
  • inner (signal) +
  • global (affects all locations, e.g. the outline layer for routing) +
+

+In pcb-rnd only copper layers and the outline layer are fully explicit. +There are two hardwired silk layers, one for the top and one for the bottom side. +The silk layers are semi-explicit: they are existing layers in all structs +but: +

    +
  • they are not part of the layer group system +
  • unlike explicit layers they have fixed index (+1 and +2 beyond the last explicit layer) +
  • created an moved by the core automatically +
  • can not be removed +
+

+The outline layer is a hack: it's really an internal copper layer. If +the code detects the name of the layer is "outline" anywhere, it branches. +

+There are a few virtual layers: +

    +
  • [top|bottom] mask - no layer struct, calculated on-the-fly from pad data +
  • [top|bottom] paste - no layer struct, calculated on-the-fly from pad data +
  • Subcircuits - no layer struct, calculated on-the-fly from pad data +
  • 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 via: +it has a hole and the same copper ring on all layers. Another global +object pcb_data_t holds is an element. An element can have pads +on two copper layers and pins that affect all layers the same way as vias. +

+The third 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. +

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

map

+ Index: tags/1.2.7/doc/developer/data1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/data1.png =================================================================== --- tags/1.2.7/doc/developer/data1.png (nonexistent) +++ tags/1.2.7/doc/developer/data1.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/data1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/ddrc/examples1.txt =================================================================== --- tags/1.2.7/doc/developer/ddrc/examples1.txt (nonexistent) +++ tags/1.2.7/doc/developer/ddrc/examples1.txt (revision 13657) @@ -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/1.2.7/doc/developer/ddrc/proposal1.txt =================================================================== --- tags/1.2.7/doc/developer/ddrc/proposal1.txt (nonexistent) +++ tags/1.2.7/doc/developer/ddrc/proposal1.txt (revision 13657) @@ -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/1.2.7/doc/developer/ddrc/requirements.txt =================================================================== --- tags/1.2.7/doc/developer/ddrc/requirements.txt (nonexistent) +++ tags/1.2.7/doc/developer/ddrc/requirements.txt (revision 13657) @@ -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/1.2.7/doc/developer/distros.txt =================================================================== --- tags/1.2.7/doc/developer/distros.txt (nonexistent) +++ tags/1.2.7/doc/developer/distros.txt (revision 13657) @@ -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/1.2.7/doc/developer/hid_gtk3/Makefile =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/Makefile (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/Makefile (revision 13657) @@ -0,0 +1,3 @@ +%.html: %.adoc + #asciidoctor --safe-mode=secure $^ + asciidoctor --safe-mode=safe $^ Index: tags/1.2.7/doc/developer/hid_gtk3/adoc_common_attributes.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/adoc_common_attributes.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/adoc_common_attributes.adoc (revision 13657) @@ -0,0 +1,12 @@ +:toc: left +:icons: font +:stylesdir: ./ +:stylesheet: default.css +:linkcss: + +// Substitutions... +:prg: pass:q[`pcb-rnd`] +:yes: icon:check[role="green"] +:no: icon:times[role="red"] +//:yes: pass:q[OK] +//:no: pass:q[NO] Index: tags/1.2.7/doc/developer/hid_gtk3/default.css =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/default.css (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/default.css (revision 13657) @@ -0,0 +1,358 @@ +/* pcb-rnd (c) Alain Vigne*/ +@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Sans:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block} +[hidden],template{display:none} +script{display:none!important} +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%} +a{background:transparent} +a:focus{outline:thin dotted} +a:active,a:hover{outline:0} +h1{font-size:2em;margin:.67em 0} +abbr[title]{border-bottom:1px dotted} +b,strong{font-weight:bold} +hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0} +mark{background:#ff0;color:#000} +code,kbd,pre,samp{font-family:monospace;font-size:1em} +pre{white-space:pre-wrap} +q{quotes:"\201C" "\201D" "\2018" "\2019"} +small{font-size:80%} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sup{top:-.5em} +sub{bottom:-.25em} +img{border:0} +svg:not(:root){overflow:hidden} +figure{margin:0} +legend{border:0;padding:0} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0} +button,input{line-height:normal} +button,select{text-transform:none} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer} +button[disabled],html input[disabled]{cursor:default} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0} +input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box} +input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0} +textarea{overflow:auto;vertical-align:top} +table{border-collapse:collapse;border-spacing:0} +*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box} +html,body{font-size:100%} +body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Sans","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased} +a:hover{cursor:pointer} +img,object,embed{max-width:100%;height:auto} +object,embed{height:100%} +img{-ms-interpolation-mode:bicubic} +.left{float:left!important} +.right{float:right!important} +.text-left{text-align:left!important} +.text-right{text-align:right!important} +.text-center{text-align:center!important} +.text-justify{text-align:justify!important} +.hide{display:none} +img,object,svg{display:inline-block;vertical-align:middle} +textarea{height:auto;min-height:50px} +select{width:100%} +.center{margin-left:auto;margin-right:auto} +.spread{width:100%} +p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6} +.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em} +div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr} +a{color:#2156a5;text-decoration:underline;line-height:inherit} +a:hover,a:focus{color:#1d4b8f} +a img{border:none} +p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility} +p aside{font-size:.875em;line-height:1.35;font-style:italic} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#804419;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em} +h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0} +h1{font-size:2.125em} +h2{font-size:1.6875em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em} +h4,h5{font-size:1.125em} +h6{font-size:1em} +hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0} +em,i{font-style:italic;line-height:inherit} +strong,b{font-weight:bold;line-height:inherit} +small{font-size:60%;line-height:inherit} +code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)} +ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit} +ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em} +ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em} +ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit} +ul.square{list-style-type:square} +ul.circle{list-style-type:circle} +ul.disc{list-style-type:disc} +ul.no-bullet{list-style:none} +ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0} +dl dt{margin-bottom:.3125em;font-weight:bold} +dl dd{margin-bottom:1.25em} +abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help} +abbr{text-transform:none} +blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd} +blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)} +blockquote cite:before{content:"\2014 \0020"} +blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)} +blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)} +@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2} +h1{font-size:2.75em} +h2{font-size:2.3125em} +h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em} +h4{font-size:1.4375em}} +table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede} +table thead,table tfoot{background:#f7f8f7;font-weight:bold} +table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left} +table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)} +table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7} +table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6} +h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em} +h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400} +.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table} +.clearfix:after,.float-group:after{clear:both} +*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word} +*:not(pre)>code.nobreak{word-wrap:normal} +*:not(pre)>code.nowrap{white-space:nowrap} +pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed} +em em{font-style:normal} +strong strong{font-weight:400} +.keyseq{color:rgba(51,51,51,.8)} +kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap} +.keyseq kbd:first-child{margin-left:0} +.keyseq kbd:last-child{margin-right:0} +.menuseq,.menu{color:rgba(0,0,0,.8)} +b.button:before,b.button:after{position:relative;top:-1px;font-weight:400} +b.button:before{content:"[";padding:0 3px 0 2px} +b.button:after{content:"]";padding:0 2px 0 3px} +p a>code:hover{color:rgba(0,0,0,.9)} +#header,#content,#footnotes,#footer{width:95%;margin-left:2em;margin-right:auto;margin-top:0;margin-bottom:0;/*max-width:62.5em;*/*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em} +#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table} +#header:after,#content:after,#footnotes:after,#footer:after{clear:both} +#content{margin-top:1.25em} +#content:before{content:none} +#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0} +#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8} +#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px} +#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap} +#header .details span:first-child{margin-left:-.125em} +#header .details span.email a{color:rgba(0,0,0,.85)} +#header .details br{display:none} +#header .details br+span:before{content:"\00a0\2013\00a0"} +#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)} +#header .details br+span#revremark:before{content:"\00a0|\00a0"} +#header #revnumber{text-transform:capitalize} +#header #revnumber:after{content:"\00a0"} +#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem} +#toc{border-bottom:1px solid #efefed;padding-bottom:.5em} +#toc>ul{margin-left:.125em} +#toc ul.sectlevel0>li>a{font-style:italic} +#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0} +#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none} +#toc li{line-height:1.3334;margin-top:.3334em} +#toc a{text-decoration:none} +#toc a:active{text-decoration:underline} +#toctitle{color:#7a2518;font-size:1.2em} +body.toc2{padding-left:20em;padding-right:0} +#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:20em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto} +#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em} +#toc.toc2>ul{font-size:.9em;margin-bottom:0} +#toc.toc2 ul ul{margin-left:0;padding-left:1em} +#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em} +body.toc2.toc-right{padding-left:0;padding-right:15em} +body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}} +.sect1+.sect1{border-top:1px solid #efefed} +#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400} +#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em} +#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible} +#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none} +#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221} +#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em} +#footer-text{color:rgba(255,255,255,.8);line-height:1.44} +.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em} +.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Sans","DejaVu Serif",serif;font-size:1rem;font-style:italic} +table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0} +.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)} +table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit} +.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%} +.admonitionblock>table td.icon{text-align:center;width:80px} +.admonitionblock>table td.icon img{max-width:none} +.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase} +.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)} +.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0} +.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px} +.exampleblock>.content>:first-child{margin-top:0} +.exampleblock>.content>:last-child{margin-bottom:0} +.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px} +.sidebarblock>:first-child{margin-top:0} +.sidebarblock>:last-child{margin-bottom:0} +.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center} +.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0} +.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8} +.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1} +.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em} +.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal} +.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em} +.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)} +.listingblock pre.highlightjs{padding:0} +.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px} +.listingblock pre.prettyprint{border-width:0} +.listingblock>.content{position:relative} +.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999} +.listingblock:hover code[data-lang]:before{display:block} +.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999} +.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"} +table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none} +table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45} +table.pyhltable td.code{padding-left:.75em;padding-right:0} +pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8} +pre.pygments .lineno{display:inline-block;margin-right:.25em} +table.pyhltable .linenodiv{background:none!important;padding-right:0!important} +.quoteblock{margin:0 1em 1.25em 1.5em;display:table} +.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em} +.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify} +.quoteblock blockquote{margin:0;padding:0;border:0} +.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)} +.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0} +.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right} +.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)} +.quoteblock .quoteblock blockquote{padding:0 0 0 .75em} +.quoteblock .quoteblock blockquote:before{display:none} +.verseblock{margin:0 1em 1.25em 1em} +.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility} +.verseblock pre strong{font-weight:400} +.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex} +.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic} +.quoteblock .attribution br,.verseblock .attribution br{display:none} +.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)} +.quoteblock.abstract{margin:0 0 1.25em 0;display:block} +.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0} +.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none} +table.tableblock{max-width:100%;border-collapse:separate} +table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0} +table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede} +table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0} +table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0} +table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0} +table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0} +table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0} +table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0} +table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0} +table.frame-all{border-width:1px} +table.frame-sides{border-width:0 1px} +table.frame-topbot{border-width:1px 0} +th.halign-left,td.halign-left{text-align:left} +th.halign-right,td.halign-right{text-align:right} +th.halign-center,td.halign-center{text-align:center} +th.valign-top,td.valign-top{vertical-align:top} +th.valign-bottom,td.valign-bottom{vertical-align:bottom} +th.valign-middle,td.valign-middle{vertical-align:middle} +table thead th,table tfoot th{font-weight:bold} +tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7} +tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold} +p.tableblock>code:only-child{background:none;padding:0} +p.tableblock{font-size:1em} +td>div.verse{white-space:pre} +ol{margin-left:1.75em} +ul li ol{margin-left:1.5em} +dl dd{margin-left:1.125em} +dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0} +ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em} +ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none} +ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em} +ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em} +ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px} +ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden} +ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block} +ul.inline>li>*{display:block} +.unstyled dl dt{font-weight:400;font-style:normal} +ol.arabic{list-style-type:decimal} +ol.decimal{list-style-type:decimal-leading-zero} +ol.loweralpha{list-style-type:lower-alpha} +ol.upperalpha{list-style-type:upper-alpha} +ol.lowerroman{list-style-type:lower-roman} +ol.upperroman{list-style-type:upper-roman} +ol.lowergreek{list-style-type:lower-greek} +.hdlist>table,.colist>table{border:0;background:none} +.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none} +td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em} +td.hdlist1{font-weight:bold;padding-bottom:1.25em} +.literalblock+.colist,.listingblock+.colist{margin-top:-.5em} +.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1} +.colist>table tr>td:last-of-type{padding:.25em 0} +.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd} +.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0} +.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em} +.imageblock>.title{margin-bottom:0} +.imageblock.thumb,.imageblock.th{border-width:6px} +.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em} +.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0} +.image.left{margin-right:.625em} +.image.right{margin-left:.625em} +a.image{text-decoration:none;display:inline-block} +a.image object{pointer-events:none} +sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super} +sup.footnote a,sup.footnoteref a{text-decoration:none} +sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline} +#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em} +#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0} +#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em} +#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none} +#footnotes .footnote:last-of-type{margin-bottom:0} +#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0} +.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0} +.gist .file-data>table td.line-data{width:99%} +div.unbreakable{page-break-inside:avoid} +.big{font-size:larger} +.small{font-size:smaller} +.underline{text-decoration:underline} +.overline{text-decoration:overline} +.line-through{text-decoration:line-through} +.aqua{color:#00bfbf} +.aqua-background{background-color:#00fafa} +.black{color:#000} +.black-background{background-color:#000} +.blue{color:#0000bf} +.blue-background{background-color:#0000fa} +.fuchsia{color:#bf00bf} +.fuchsia-background{background-color:#fa00fa} +.gray{color:#606060} +.gray-background{background-color:#7d7d7d} +.green{color:#006000} +.green-background{background-color:#007d00} +.lime{color:#00bf00} +.lime-background{background-color:#00fa00} +.maroon{color:#600000} +.maroon-background{background-color:#7d0000} +.navy{color:#000060} +.navy-background{background-color:#00007d} +.olive{color:#606000} +.olive-background{background-color:#7d7d00} +.purple{color:#600060} +.purple-background{background-color:#7d007d} +.red{color:#bf0000} +.red-background{background-color:#fa0000} +.silver{color:#909090} +.silver-background{background-color:#bcbcbc} +.teal{color:#006060} +.teal-background{background-color:#007d7d} +.white{color:#bfbfbf} +.white-background{background-color:#fafafa} +.yellow{color:#bfbf00} +.yellow-background{background-color:#fafa00} +span.icon>.fa{cursor:default} +.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default} +.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c} +.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111} +.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900} +.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400} +.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000} +.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold} +.conum[data-value] *{color:#fff!important} +.conum[data-value]+b{display:none} +.conum[data-value]:after{content:attr(data-value)} +pre .conum[data-value]{position:relative;top:-.125em} +b.conum *{color:inherit!important} +.conum:not([data-value]):empty{display:none} +dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility} +h1,h2,p,td.content,span.alt{letter-spacing:-.01em} +p strong,td.content strong,div.footnote strong{letter-spacing:-.005em} +p,blockquote,dt,td.content,span.alt{font-size:1.0625rem} +p{margin-bottom:1.25rem} +.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em} +.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc} Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.adoc (revision 13657) @@ -0,0 +1,5 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += DRC results GUI + Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_drc_dialog.html (revision 13657) @@ -0,0 +1,29 @@ + + + + + + + + +DRC results GUI + + + + + +
+ +
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.adoc (revision 13657) @@ -0,0 +1,295 @@ +:author: Alain, Igor2 +include::adoc_common_attributes.adoc[] + += GTK HID architecture + +== Situation @ {prg} v1.2.1 +The HIDs are plug-ins, sitting in `src_plugins/hid_*` ; GTK2 one is called `hid_gtk`. + +First, get an instance of the main HID structure `pcb_hid_t`. +This structure is general enough. Nothing too entangled to GTK2 nor GTK3 there. +```c +pcb_hid_t pcb_gui = pcb_hid_find_gui () +``` + +Q: How GTK HID is initialized ? + +A: `hid_hid_gtk_init ()` in `` + +The GUI seems to start building from `ghid_do_export ()` + +There are 2 big structures for GTK2 GUI: +```c +GhidGui _ghidgui, *ghidgui = &_ghidgui; + +GHidPort ghid_port, *gport; +``` + +GTK3 compatibility within these 2 structures: + +.`GhidGui` structure study (portion) +[options="header"] +|=== +| Type | GTK3 compatible | GTK3 replacement | GTK2 compatible ? +| GtkWidget | {yes} | | +| GtkObject | {no} | GObject | could be +| GdkPixmap | {no} | GdkPixbuf | could be +| GtkAction | deprecated | GAction (gio) | could be (not desired) +| GtkActionGroup | {no} | GActionGroup | {no} (not desired) +| GtkEntry | {yes} | | +| GTimeVal | {yes} (glib) | | +|=== + + +.`GHidPort` structure study (portion) +[options="header"] +|=== +| Type | GTK+3 compatible | GTK+3 replacement | GTK+2 compatible ? +| GtkWidget | {yes} | | +| GdkPixmap | {no} | GdkPixbuf | could be +| GdkDrawable | {no} | Cairo surface | {no} (not desired) +| GdkColor | {no} | GdkRGBA | {no}^1^ +| GdkColormap | {no} | GdkVisual | {no}^1^ +|=== +^1^ An abstracted structure was envisioned, but abandoned due to scarce use of color objects. + + +== Drawing primitives using GDKx +=== GDK2 +{prg} v1.2.1 is using `gdk_draw...` functions, on an already abstracted +`pcb_hid_t` intance of `hid_gc_s` structure. + +.`hid_gc_s` structure study (portion) +[options="header"] +|=== +| Type | GTK+3 compatible | GTK+3 replacement | GTK+2 compatible ? +| GdkGC | {no} | Cairo context | could be (not desired) +|=== + +Indirectly, a `GdkGC` needs a `GdkDrawable` which is also deprecated in GTK3. +A good replacement is a `GdkWindow`. Unfortunately {prg} is making more use +of deprecated `GdkPixmap` objects than `GdkWindow`. + +`gdk_draw_line` has been deprecated since GTK+ 2.22. Use `cairo_line_to` + and `cairo_stroke` instead. `gdk_gc_new` has been deprecated since GTK+ 2.22. + Use Cairo for rendering. + +Cairo API needs a context: +```c +cairo_line_to (cairo_t *cr, + double x, + double y); +cairo_t * +cairo_create (cairo_surface_t *target); +``` +and then pops-up the *Cairo Surface* ! + +A `cairo_surface_t` represents an image, either as the destination of a +drawing operation or as source when drawing onto another surface. + +GDK does not wrap the cairo API, instead it allows to create cairo contexts +which can be used to draw on `GdkWindow`. Additional functions allow use +`GdkRectangles` with cairo and to use `GdkColors`, `GdkRGBAs`, `GdkPixbufs` +and `GdkWindows` as sources for drawing operations. + +=== GDK3 +=== Cairo Interaction +Cairo is a graphics library that supports vector graphics and image compositing +that can be used with GDK. GTK+ does all of its drawing using cairo. +But I guess, it is also the case with late GDK2 ! + +=== Open GL +`GdkGLContext` is an object representing the platform-specific OpenGL drawing context. + +=== Very modern GDK3 +`GdkDrawingContext` is an object that represents the current drawing state of a `GdkWindow`. +It's possible to use a `GdkDrawingContext` to draw on a `GdkWindow` via +rendering API like Cairo or OpenGL. + +Since: 3.22 + +== Plans for {prg} v1.2.2 ? + +//Please note that I don't see much sense in doing a gtk2+cairo. +//I don't say we can't do it as a temporary option, but I say it would be a waste of time. +//My reasoning: + +. What we must have: + +.. the old gtk2 HID, with pixmaps and all the existing obsolete code - for +existing/old systems. We won't remove or change this, there's absolutely +no reason to risk running on older systems. We probably won't remove +it in any time soon, because some people love to run real OLD systems. + +.. whichever gtk HID with *gl* rendering; let's say _gtk2+gl_, because gtk2 is +what we have working today. This seems to be real appealing for many users. + + +. [[future]] What extras we could have and totally makes sense: + +.. the new, gtk3 HID, with Cairo for sw rendering, because as far as +I understand there's no other option for sw rendering in gtk3 + +.. the new, gtk3 HID with *gl* rendering + +. What we could temporarily have, if it helped us on our way to <>: + +.. a temporary, hidden, development _gtk2+cairo_ implementation so +that cairo can be done in something that's already there before +gtk3 happens. This must not interfere with the gdk/pixmap implementation. +This must not remain for long in the repo, and must be converted into +the _gtk3+cairo_ hid ASAP. + +. What we shouldn't have because it doesn't make much sense but increases the +confusion and development/maintainance costs: + +.. a permanent, advertised gtk2+cairo HID. gtk2 works perfectly fine with +existing installation and the existing code. Cairo can only add slowdown +to this and introduces new build risks. Old systems don't need cairo to work. +New systems will have gtk3 sooner or layer anyway. Other than a few "obsolete" +marks in the manual, there's absolutely no issue with a _gtk2+pixmap_. + +=== Roadmap (short term) + +* keep pushing the `lib_gtk_common` split, trying to isolate general concepts + from low-level GDK2 / GDK3 details. +* Name policy on object / functions in `lib_gtk_common` ? +* Agree on names for "top" level objects / structures, and start implementation + in `hid_gtk3` for those high level structures. +* Open thinking about infrastructure for menus and actions, but don't change a thing yet. + +=== Names proposal +[options="header"] +|=== +| Before | After +| GhidGui | pcb_gtk_gui_t +| extern GhidGui _ghidgui, *ghidgui; | pcb_gtk_gui_t _pcb_gtk_gui, *pcb_gtk_gui; +| GHidPort | pcb_gtk_viewport_t +| extern GHidPort ghid_port, *gport; | pcb_gtk_viewport_t _pcb_gtk_viewport *pcb_gtk_viewport +|=== + +=== Situation `svn r7460` + +```sh +├── hid_gtk +│   ├── actions.c +│   ├── colors.c +│   ├── common.c +│   ├── glue_common.c +│   ├── glue_conf.c +│   ├── glue_event.c +│   ├── glue_hid.c +│   ├── glue_win32.c +│   ├── gtkhid-gdk.c +│   ├── gtkhid-gl.c +│   └── gtkhid-main.c +├── hid_gtk3 +│   └── colors.c +├── lib_gtk_common +│   ├── act_fileio.c +│   ├── act_print.c +│   ├── bu_*.c +│   ├── dlg_*.c +│   ├── dlg_topwin.c +│   ├── in_keyboard.c +│   ├── in_mouse.c +│   ├── lib_gtk_common.c +│   ├── ui_crosshair.c +│   ├── ui_zoompan.c +│   ├── util_block_hook.c +│   ├── util_ext_chg.c +│   ├── util_listener.c +│   ├── util_str.c +│   ├── util_timer.c +│   ├── util_watch.c +│   ├── win_place.c +│   └── wt_*.c +├── lib_gtk_config +│   ├── gtk_conf_list.c +│   ├── gui-config.c +│   └── lib_gtk_config.c +``` + +.bu_* +```sh +box +check_button +cursor_pos +dwg_tooltip +entry +icons +info_bar +layer_selector +menu +mode_btn +notebook +spin_button +status_line +text_view +``` + +.dlg_* +```sh +about +attribute +command +confirm +drc +drc_cr +export +file_chooser +fontsel +input +library +library_param +log +message +netlist +pinout +print +progress +propedit +report +route_style +search +``` + +.wt_* +```sh +accel_label.c +coord_entry.c +layer_selector.c +layer_selector_cr.c +preview.c +route_style.c +``` + +==== GUI creation Timeline +[options="header",cols="4*m"] +|=== +| function | directory | file | structure / data +| hid_hid_gtk_init | hid_gtk/ | gtkhid-main.c | GhidGui _ghidgui, *ghidgui = &_ghidgui; +| ghid_glue_common_init | hid_gtk/ | glue_common.c | GHidPort ghid_port, *gport; +| ghid_glue_hid_init | hid_gtk/ | glue_hid.c | pcb_hid_t ghid_hid; +| glue_event_init | hid_gtk/ | glue_event.c | +| ghid_do_export | hid_gtk/ | glue_hid.c | +| pcb_hid_cfg_keys_init | src/ | hid_cfg_input.c | pcb_hid_cfg_keys_t ghid_keymap; +| ghid_create_pcb_widgets | lib_gtk_common/ | dlg_topwin.c | +|=== + +==== `glue.h` +FIXME: draw relationships between "top level" structures, and common, config + +Detail common GTK2/GTK3 features ; distinguish between low level GTK2/3 ones. + +== Road blocks ahead + +Thinking about: + +* Menus : Split Application menus and _per topic_ contextual menus. +** Actions : use `GAction` if needed +** Short cut, multi-key shortcuts : + +Suggests more use of GIO : https://developer.gnome.org/gio/stable/ch01.html + + Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_hid_architecture.html (revision 13657) @@ -0,0 +1,628 @@ + + + + + + + + +GTK HID architecture + + + + + +
+
+

Situation @ pcb-rnd v1.2.1

+
+
+

The HIDs are plug-ins, sitting in src_plugins/hid_* ; GTK2 one is called hid_gtk.

+
+
+

First, get an instance of the main HID structure pcb_hid_t. +This structure is general enough. Nothing too entangled to GTK2 nor GTK3 there.

+
+
+
+
pcb_hid_t pcb_gui = pcb_hid_find_gui ()
+
+
+
+

Q: How GTK HID is initialized ?

+
+
+

A: hid_hid_gtk_init () in <hid_gtk/gtkhid-main.c>

+
+
+

The GUI seems to start building from ghid_do_export ()

+
+
+

There are 2 big structures for GTK2 GUI:

+
+
+
+
GhidGui _ghidgui, *ghidgui = &_ghidgui;
+
+GHidPort ghid_port, *gport;
+
+
+
+

GTK3 compatibility within these 2 structures:

+
+ + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table 1. GhidGui structure study (portion)
TypeGTK3 compatibleGTK3 replacementGTK2 compatible ?

GtkWidget

GtkObject

GObject

could be

GdkPixmap

GdkPixbuf

could be

GtkAction

deprecated

GAction (gio)

could be (not desired)

GtkActionGroup

GActionGroup

(not desired)

GtkEntry

GTimeVal

(glib)

+ + ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Table 2. GHidPort structure study (portion)
TypeGTK+3 compatibleGTK+3 replacementGTK+2 compatible ?

GtkWidget

GdkPixmap

GdkPixbuf

could be

GdkDrawable

Cairo surface

(not desired)

GdkColor

GdkRGBA

1

GdkColormap

GdkVisual

1

+
+

1 An abstracted structure was envisioned, but abandoned due to scarce use of color objects.

+
+
+
+
+

Drawing primitives using GDKx

+
+
+

GDK2

+
+

pcb-rnd v1.2.1 is using gdk_draw…​ functions, on an already abstracted +pcb_hid_t intance of hid_gc_s structure.

+
+ + ++++++ + + + + + + + + + + + + + + + + +
Table 3. hid_gc_s structure study (portion)
TypeGTK+3 compatibleGTK+3 replacementGTK+2 compatible ?

GdkGC

Cairo context

could be (not desired)

+
+

Indirectly, a GdkGC needs a GdkDrawable which is also deprecated in GTK3. +A good replacement is a GdkWindow. Unfortunately pcb-rnd is making more use +of deprecated GdkPixmap objects than GdkWindow.

+
+
+

gdk_draw_line has been deprecated since GTK+ 2.22. Use cairo_line_to + and cairo_stroke instead. gdk_gc_new has been deprecated since GTK+ 2.22. + Use Cairo for rendering.

+
+
+

Cairo API needs a context:

+
+
+
+
cairo_line_to (cairo_t *cr,
+               double x,
+               double y);
+cairo_t *
+cairo_create (cairo_surface_t *target);
+
+
+
+

and then pops-up the Cairo Surface !

+
+
+

A cairo_surface_t represents an image, either as the destination of a +drawing operation or as source when drawing onto another surface.

+
+
+

GDK does not wrap the cairo API, instead it allows to create cairo contexts +which can be used to draw on GdkWindow. Additional functions allow use +GdkRectangles with cairo and to use GdkColors, GdkRGBAs, GdkPixbufs +and GdkWindows as sources for drawing operations.

+
+
+
+

GDK3

+ +
+
+

Cairo Interaction

+
+

Cairo is a graphics library that supports vector graphics and image compositing +that can be used with GDK. GTK+ does all of its drawing using cairo. +But I guess, it is also the case with late GDK2 !

+
+
+
+

Open GL

+
+

GdkGLContext is an object representing the platform-specific OpenGL drawing context.

+
+
+
+

Very modern GDK3

+
+

GdkDrawingContext is an object that represents the current drawing state of a GdkWindow. +It’s possible to use a GdkDrawingContext to draw on a GdkWindow via +rendering API like Cairo or OpenGL.

+
+
+

Since: 3.22

+
+
+
+
+
+

Plans for pcb-rnd v1.2.2 ?

+
+
+
    +
  1. +

    What we must have:

    +
    +
      +
    1. +

      the old gtk2 HID, with pixmaps and all the existing obsolete code - for +existing/old systems. We won’t remove or change this, there’s absolutely +no reason to risk running on older systems. We probably won’t remove +it in any time soon, because some people love to run real OLD systems.

      +
    2. +
    3. +

      whichever gtk HID with gl rendering; let’s say gtk2+gl, because gtk2 is +what we have working today. This seems to be real appealing for many users.

      +
    4. +
    +
    +
  2. +
  3. +

    What extras we could have and totally makes sense:

    +
    +
      +
    1. +

      the new, gtk3 HID, with Cairo for sw rendering, because as far as +I understand there’s no other option for sw rendering in gtk3

      +
    2. +
    3. +

      the new, gtk3 HID with gl rendering

      +
    4. +
    +
    +
  4. +
  5. +

    What we could temporarily have, if it helped us on our way to previous:

    +
    +
      +
    1. +

      a temporary, hidden, development gtk2+cairo implementation so +that cairo can be done in something that’s already there before +gtk3 happens. This must not interfere with the gdk/pixmap implementation. +This must not remain for long in the repo, and must be converted into +the gtk3+cairo hid ASAP.

      +
    2. +
    +
    +
  6. +
  7. +

    What we shouldn’t have because it doesn’t make much sense but increases the +confusion and development/maintainance costs:

    +
    +
      +
    1. +

      a permanent, advertised gtk2+cairo HID. gtk2 works perfectly fine with +existing installation and the existing code. Cairo can only add slowdown +to this and introduces new build risks. Old systems don’t need cairo to work. +New systems will have gtk3 sooner or layer anyway. Other than a few "obsolete" +marks in the manual, there’s absolutely no issue with a gtk2+pixmap.

      +
    2. +
    +
    +
  8. +
+
+
+

Roadmap (short term)

+
+
    +
  • +

    keep pushing the lib_gtk_common split, trying to isolate general concepts +from low-level GDK2 / GDK3 details.

    +
  • +
  • +

    Name policy on object / functions in lib_gtk_common ?

    +
  • +
  • +

    Agree on names for "top" level objects / structures, and start implementation +in hid_gtk3 for those high level structures.

    +
  • +
  • +

    Open thinking about infrastructure for menus and actions, but don’t change a thing yet.

    +
  • +
+
+
+
+

Names proposal

+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
BeforeAfter

GhidGui

pcb_gtk_gui_t

extern GhidGui _ghidgui, *ghidgui;

pcb_gtk_gui_t _pcb_gtk_gui, *pcb_gtk_gui;

GHidPort

pcb_gtk_viewport_t

extern GHidPort ghid_port, *gport;

pcb_gtk_viewport_t _pcb_gtk_viewport *pcb_gtk_viewport

+
+
+

Situation svn r7460

+
+
+
├── hid_gtk
+│   ├── actions.c
+│   ├── colors.c
+│   ├── common.c
+│   ├── glue_common.c
+│   ├── glue_conf.c
+│   ├── glue_event.c
+│   ├── glue_hid.c
+│   ├── glue_win32.c
+│   ├── gtkhid-gdk.c
+│   ├── gtkhid-gl.c
+│   └── gtkhid-main.c
+├── hid_gtk3
+│   └── colors.c
+├── lib_gtk_common
+│   ├── act_fileio.c
+│   ├── act_print.c
+│   ├── bu_*.c
+│   ├── dlg_*.c
+│   ├── dlg_topwin.c
+│   ├── in_keyboard.c
+│   ├── in_mouse.c
+│   ├── lib_gtk_common.c
+│   ├── ui_crosshair.c
+│   ├── ui_zoompan.c
+│   ├── util_block_hook.c
+│   ├── util_ext_chg.c
+│   ├── util_listener.c
+│   ├── util_str.c
+│   ├── util_timer.c
+│   ├── util_watch.c
+│   ├── win_place.c
+│   └── wt_*.c
+├── lib_gtk_config
+│   ├── gtk_conf_list.c
+│   ├── gui-config.c
+│   └── lib_gtk_config.c
+
+
+
+
bu_*
+
+
box
+check_button
+cursor_pos
+dwg_tooltip
+entry
+icons
+info_bar
+layer_selector
+menu
+mode_btn
+notebook
+spin_button
+status_line
+text_view
+
+
+
+
dlg_*
+
+
about
+attribute
+command
+confirm
+drc
+drc_cr
+export
+file_chooser
+fontsel
+input
+library
+library_param
+log
+message
+netlist
+pinout
+print
+progress
+propedit
+report
+route_style
+search
+
+
+
+
wt_*
+
+
accel_label.c
+coord_entry.c
+layer_selector.c
+layer_selector_cr.c
+preview.c
+route_style.c
+
+
+
+

GUI creation Timeline

+ ++++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functiondirectoryfilestructure / data

hid_hid_gtk_init

hid_gtk/

gtkhid-main.c

GhidGui _ghidgui, *ghidgui = &_ghidgui;

ghid_glue_common_init

hid_gtk/

glue_common.c

GHidPort ghid_port, *gport;

ghid_glue_hid_init

hid_gtk/

glue_hid.c

pcb_hid_t ghid_hid;

glue_event_init

hid_gtk/

glue_event.c

ghid_do_export

hid_gtk/

glue_hid.c

pcb_hid_cfg_keys_init

src/

hid_cfg_input.c

pcb_hid_cfg_keys_t ghid_keymap;

ghid_create_pcb_widgets

lib_gtk_common/

dlg_topwin.c

+
+
+

glue.h

+
+

FIXME: draw relationships between "top level" structures, and common, config

+
+
+

Detail common GTK2/GTK3 features ; distinguish between low level GTK2/3 ones.

+
+
+
+
+
+
+

Road blocks ahead

+
+
+

Thinking about:

+
+
+
    +
  • +

    Menus : Split Application menus and per topic contextual menus.

    +
    +
      +
    • +

      Actions : use GAction if needed

      +
    • +
    • +

      Short cut, multi-key shortcuts :

      +
    • +
    +
    +
  • +
+
+ +
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc (revision 13657) @@ -0,0 +1,65 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += GTK "Preferences Dialog" + +== Requirements +* The window should fit 800x600 screen configurations. +* The preferences should be consistent troughout the dialog, honored and refreshed. +* All preferences types should be "bug free" ! + +== Current implementation +=== Size +Size requested: 780x550. Realized so far : 780x591 + +There is a "dynamic area" in `Config PoV` where all the widgets needed to edit +different data types are created, but then, only displayed + +GTK realizes all those widgets, which is taking a lot of Y space, while +during real user interaction, only a few widgets are displayed, minimising the +required Y space... I tried to connect a `realize` signal to recalculate +the widget size, but does not seem to work :( + +=== Jump on `Save` +In `User PoV`, when clicking on `Save in config` ?? (else too ?) there is an ugly workaround: + +The whole preferences dialog was designed to be built up once, with all +values copied from core to GTK then copied back from GTK to core on dialog close. +This means if any value is updated on the fly, it's not trivial to make sure the +gtk mirror is updated. + +As a workaround, we just force it in a state that the tabs need to be re-created. + +This is not nice, but the real fix would be very expensive. The config system +is strong on this, it supports calling back functions on config value changes, +so it would be easy to get the conf system to notify the gtk code when the +change happens. But on the GTK side we don't have any infra or code for this. +And a partial solution wouldn't help - if we wanted to do this, we'd need to +do this for all values, including the tricky ones (prio lists even in the config pov section). +Would take weeks or even months to get it right. Not sure it is worth the effort. + +So, on save, the dialog is destroyed and recreated, jumping at the same tab in +the tree view. This has some bugs. FIXME them ! + +On the other hand, there could be yet another workaround on this: we could +remember what tree node was open when we triggered this, and then after the +rebuild, we could just open that again. Go Alain ! + +=== Problems with some types +* increments +* layers +* groups + +=== Code explanation + +//image::gtk_preferences_dialog.svg[] + + +`static GtkWidget *config_window;` + +is the total dialog window. + + + + +== TODO Index: tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/gtk_preferences_dialog.html (revision 13657) @@ -0,0 +1,146 @@ + + + + + + + + +GTK "Preferences Dialog" + + + + + +
+
+

Requirements

+
+
+
    +
  • +

    The window should fit 800x600 screen configurations.

    +
  • +
  • +

    The preferences should be consistent troughout the dialog, honored and refreshed.

    +
  • +
  • +

    All preferences types should be "bug free" !

    +
  • +
+
+
+
+
+

Current implementation

+
+
+

Size

+
+

Size requested: 780x550. Realized so far : 780x591

+
+
+

There is a "dynamic area" in Config PoV where all the widgets needed to edit +different data types are created, but then, only displayed

+
+
+

GTK realizes all those widgets, which is taking a lot of Y space, while +during real user interaction, only a few widgets are displayed, minimising the +required Y space…​ I tried to connect a realize signal to recalculate +the widget size, but does not seem to work :(

+
+
+
+

Jump on Save

+
+

In User PoV, when clicking on Save in config ?? (else too ?) there is an ugly workaround:

+
+
+

The whole preferences dialog was designed to be built up once, with all +values copied from core to GTK then copied back from GTK to core on dialog close. +This means if any value is updated on the fly, it’s not trivial to make sure the +gtk mirror is updated.

+
+
+

As a workaround, we just force it in a state that the tabs need to be re-created.

+
+
+

This is not nice, but the real fix would be very expensive. The config system +is strong on this, it supports calling back functions on config value changes, +so it would be easy to get the conf system to notify the gtk code when the +change happens. But on the GTK side we don’t have any infra or code for this. +And a partial solution wouldn’t help - if we wanted to do this, we’d need to +do this for all values, including the tricky ones (prio lists even in the config pov section). +Would take weeks or even months to get it right. Not sure it is worth the effort.

+
+
+

So, on save, the dialog is destroyed and recreated, jumping at the same tab in +the tree view. This has some bugs. FIXME them !

+
+
+

On the other hand, there could be yet another workaround on this: we could +remember what tree node was open when we triggered this, and then after the +rebuild, we could just open that again. Go Alain !

+
+
+
+

Problems with some types

+
+
    +
  • +

    increments

    +
  • +
  • +

    layers

    +
  • +
  • +

    groups

    +
  • +
+
+
+
+

Code explanation

+
+

static GtkWidget *config_window;

+
+
+

is the total dialog window.

+
+
+
+
+
+

TODO

+
+ +
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: tags/1.2.7/doc/developer/hid_gtk3/includes_directives.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/includes_directives.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/includes_directives.adoc (revision 13657) @@ -0,0 +1,77 @@ +:author: Alain, Igor2 +include::adoc_common_attributes.adoc[] + += `#include` directives + +Rules applied to {prg}, especially in directories: + +```sh +src_plugins +├── hid_gtk +├── hid_gtk3 +├── lib_gtk_common +├── lib_gtk_config +``` +== In `.h` files + +[[h_inc_all]] +=== Rule {counter:rh} +TIP: Look at the `.h` file only ; `#include` everything you need in that given file, + directly, to let the compiler understands the structures and function + protoypes used there. + +=== Rule {counter:rh} +TIP: Don't be afraid to have indirect `#include`s (`fileA` is including +`fileB` and `fileC`, but `fileB` already includes `fileC`) + +Here, do both includes, not only `fileB`. + +=== Rule {counter:rh} +TIP: Circular `#include` ? : `fileA` includes `fileB` which itself includes `fileA`... +It's perfectly fine ;) + +=== Rule {counter:rh} +TIP: Frame your `.h` code with a `#define` allowing single definition if multiple calls. +Example: +---- +#ifdef PCB_FILEA_H +#define PCB_FILEA_H + +the code + +#endif /* PCB_FILEA_H */ +---- + +=== Rule {counter:rh} +TIP: Name those define `PCB_GTK...` according to following table: + +[options="header",cols="2*m"] +|=== +| Directory | Prefix +| lib_gtk_common | PCB_GTK_ +| lib_gtk_config | PCB_GTK_ +| hid_gtk | PCB_GTK2_ +| hid_gtk3 | PCB_GTK3_ +|=== + + +== In `.c` files + +=== Rule {counter:rc} +IMPORTANT: `#include "config.h"` first... + +This is an essential mechanism for porting. + +=== Rule {counter:rc} +TIP: If the file is `fileA.c`, then `#include "fileA.h"` + +=== Rule {counter:rc} +TIP: refer to `.h` <> that can be applied to `.c` files. + +=== Rule {counter:rc} +CAUTION: please do _not_ remove `obj_elem.h` in favor of `obj_all.h` - `obj_all.h` is +a temporary construct that will be gone... + +//=== Rule {counter:rc} +//TIP: Obviously, directly `#include` everything you need in that file to let the +// compiler understands your code. \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/includes_directives.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/includes_directives.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/includes_directives.html (revision 13657) @@ -0,0 +1,263 @@ + + + + + + + + +#include directives + + + + + +
+
+
+
+

Rules applied to pcb-rnd, especially in directories:

+
+
+
+
src_plugins
+├── hid_gtk
+├── hid_gtk3
+├── lib_gtk_common
+├── lib_gtk_config
+
+
+
+
+
+

In .h files

+
+
+

Rule 1

+
+ + + + + +
+ + +Look at the .h file only ; #include everything you need in that given file, + directly, to let the compiler understands the structures and function + protoypes used there. +
+
+
+
+

Rule 2

+
+ + + + + +
+ + +Don’t be afraid to have indirect #include`s (`fileA is including +fileB and fileC, but fileB already includes fileC) +
+
+
+

Here, do both includes, not only fileB.

+
+
+
+

Rule 3

+
+ + + + + +
+ + +Circular #include ? : fileA includes fileB which itself includes fileA…​ +It’s perfectly fine ;) +
+
+
+
+

Rule 4

+
+ + + + + +
+ + +Frame your .h code with a #define allowing single definition if multiple calls. +Example: +
+
+
+
+
#ifdef  PCB_FILEA_H
+#define PCB_FILEA_H
+
+the code
+
+#endif  /* PCB_FILEA_H */
+
+
+
+
+

Rule 5

+
+ + + + + +
+ + +Name those define PCB_GTK…​ according to following table: +
+
+ ++++ + + + + + + + + + + + + + + + + + + + + + + + + +
DirectoryPrefix

lib_gtk_common

PCB_GTK_

lib_gtk_config

PCB_GTK_

hid_gtk

PCB_GTK2_

hid_gtk3

PCB_GTK3_

+
+
+
+
+

In .c files

+
+
+

Rule 1

+
+ + + + + +
+ + +#include "config.h" first…​ +
+
+
+

This is an essential mechanism for porting.

+
+
+
+

Rule 2

+
+ + + + + +
+ + +If the file is fileA.c, then #include "fileA.h" +
+
+
+
+

Rule 3

+
+ + + + + +
+ + +refer to .h rules that can be applied to .c files. +
+
+
+
+

Rule 4

+
+ + + + + +
+ + +please do not remove obj_elem.h in favor of obj_all.h - obj_all.h is +a temporary construct that will be gone…​ +
+
+
+
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/index.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/index.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/index.adoc (revision 13657) @@ -0,0 +1,36 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += GTK{2 | 3 | 4} GUI related topics + +* My understanding/roadmap for <>. +** GTK3 using `cairo` back-end versus GDK +//** Prefer `GdkPixbuf` to `GdkPixmap` or `GdkBitmap` +//** Get rid of `gdk_drawable...` ; use cairo surfaces + +* Menus, Actions : + The configurable menus system needs to be kept. + +//* Multi-key keyboard shortcuts + +== Custom widgets +* <> concepts + +* <> dialog + widget. Concepts + +* Preview widget + +== Dialogs +* <> + +* <> or windows ... Future work. + +== GTK4 new design ? + +== Developer tips + +* `\#include` directives <>. + +* ./configure --debug, then: valgrind --track-origins=yes -v ./pcb-rnd 2>Valg.log + +* Policy about copyrights ? Index: tags/1.2.7/doc/developer/hid_gtk3/index.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/index.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/index.html (revision 13657) @@ -0,0 +1,116 @@ + + + + + + + + +GTK{2 | 3 | 4} GUI related topics + + + + + +
+
+
+
+
    +
  • +

    My understanding/roadmap for GTKx HID architecture.

    +
    +
      +
    • +

      GTK3 using cairo back-end versus GDK

      +
    • +
    +
    +
  • +
  • +

    Menus, Actions +The configurable menus system needs to be kept.

    +
  • +
+
+
+
+
+

Custom widgets

+
+
+ +
+
+
+
+

Dialogs

+
+
+ +
+
+
+
+

GTK4 new design ?

+
+ +
+
+
+

Developer tips

+
+
+
    +
  • +

    #include directives policy.

    +
  • +
  • +

    ./configure --debug, then: valgrind --track-origins=yes -v ./pcb-rnd 2>Valg.log

    +
  • +
  • +

    Policy about copyrights ?

    +
  • +
+
+
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/init_sequence.dot =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/init_sequence.dot (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/init_sequence.dot (revision 13657) @@ -0,0 +1,34 @@ +/* dot -Tpng -oinit_sequence.png init_sequence.dot */ +digraph G +{ + node [shape=rect]; + + n_parse_arguments [shape=record, label="\ | pcb_gui-\>parse_arguments() | gtk3_cairo_parse_arguments()"]; + n_do_export [shape=record, label="\ | pcb_gui-\>do_export() | gtkhid_do_export()"]; + n_create_pcb_widgets [label="ghid_create_pcb_widgets()\n"]; + n_build_top_window [label="ghid_build_pcb_top_window()"]; + n_drawing_area_new [label="gtk_drawing_area_new()"]; + + "main() " -> n_parse_arguments:f0; + n_parse_arguments:f0 -> n_do_export:f0 [weight=10]; + n_do_export:f2 -> n_create_pcb_widgets; + n_create_pcb_widgets -> n_build_top_window; + n_build_top_window -> n_drawing_area_new; + n_drawing_area_new -> drawing_area; + + n_parse_arguments:f2 -> n_gtkhid_parse_arguments; + subgraph gtk3_cairo_parse_arguments { + n_gtkhid_parse_arguments [label="gtkhid_parse_arguments()\n"]; + n_init_renderer [shape=record, label="ghidgui-\>common.init_renderer | ghid_cairo_init_renderer()"]; + n_init_top_window [label="gport->top_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);"] + + n_gtkhid_parse_arguments -> n_init_renderer:f0; + n_gtkhid_parse_arguments -> n_init_top_window; + n_init_renderer -> "render_priv = g_new0(render_priv_t, 1);" + } + + subgraph drawing_area { + drawing_area -> "ghid_cairo_drawing_area_expose_cb()"; + drawing_area -> "ghid_cairo_preview_expose()"; + } +} Index: tags/1.2.7/doc/developer/hid_gtk3/init_sequence.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = image/png Index: tags/1.2.7/doc/developer/hid_gtk3/init_sequence.png =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/init_sequence.png (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/init_sequence.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/hid_gtk3/init_sequence.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +image/png \ No newline at end of property Index: tags/1.2.7/doc/developer/hid_gtk3/layer_selection.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/layer_selection.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/layer_selection.adoc (revision 13657) @@ -0,0 +1,19 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += Layer selection GUI + +:experimental: +:numbered: +== Introduction + +=== What is the Layer Selection widget +Up to {prg} v1.2.2, the Layer Selection widget resides on the left side, +underneath the menus, and presents a list of named layers. On the left +of a layer name, there is a colored rectangle : + +* fully filled if the layer is visible +* half filled if the layer is not shown. + + +== Evolution Index: tags/1.2.7/doc/developer/hid_gtk3/layer_selection.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/layer_selection.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/layer_selection.html (revision 13657) @@ -0,0 +1,61 @@ + + + + + + + + +Layer selection GUI + + + + + +
+
+

1. Introduction

+
+
+

1.1. What is the Layer Selection widget

+
+

Up to pcb-rnd v1.2.2, the Layer Selection widget resides on the left side, +underneath the menus, and presents a list of named layers. On the left +of a layer name, there is a colored rectangle

+
+
+
    +
  • +

    fully filled if the layer is visible

    +
  • +
  • +

    half filled if the layer is not shown.

    +
  • +
+
+
+
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_gtk3/route_style.adoc =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/route_style.adoc (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/route_style.adoc (revision 13657) @@ -0,0 +1,188 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += Route style GUI design + +[abstract] +== Abstract + +This document is a WIP, working document, mixture of many sources of documentation +linked to the <> GUI part, as presented to the user. + +PCB means PCB/gEDA, or mainline, {prg} is the primary focus for this WIP. + +:experimental: +:numbered: +== Introduction + +=== What is a Route Style + +The `menu:Edit[Route Styles]` menu allows you to select a style which is a group +of line thickness, via diameter, via drill size, and clearance (keepaway) +(collectively called a _routing style_) to be copied to the _active_ sizes. +You can also change the names given to the routing styles and adjust their +values from `menu:Edit[Route Styles > Edit]` menu. + +The active sizes are also adjustable from this menu (How ?). +The active sizes are shown in the status-line and control the initial size of +new vias, drilling holes, lines, clearances, text-objects and also +the maximum dimensions of the board layout. + +A routing style can be attributed to a net. (How ?, How am I sure all the +nets/lines/tracks are affected to the selected routing style ?) + +=== Using the autorouter + +Do we still have the autorouter ? Is what is described next working elsewhere ? + +Use routing styles in the netlist to have per-net routing styles. +Note that the routing style will be used for an entire net. +This means if you have a wide metal setting for a power net you will need to +manually route breakouts from any fine pitch parts on their power pins because +the router will not be able to change to a narrow trace to connect to the part. + +== Design intentions + +=== {prg} goals + +* Alleviate the limitation of 4 only different route styles. +* Keep track of "current" route style + +=== {prg} implementation prior 1.2.1 + +A radio-button area + extra <> + +==== Add a new route style + +This is ensured via the `` selection + +[[img-gtk2-edit_route]] +.Edit route styles dialog +image::gtk2-edit_route_styles_001.png[] + +Q: No `Add` button: historical reasons. The original code in mainline +has 4 route styles, hardwired. It can not remove styles. +We inherited the mechanism of adding style by selecting the ``. +(In mainline if you add styles more than 4, they are lost on save). + +The inherited code tries not to do modifications immediately but only when +you close the window. This is a common pattern in the gtk hid at the +moment: all data from core copied to some "hid_gtk-specific" mirror cache +for the dialog, then the dialog works on the cache and it is copied back +when you close the dialog. + +Igor2 thinks the idea was that the dialogs are modal and if the user says +cancel, you just don't do the copy-back. It's a lot of extra code and complication. +The strange mechanism might be a result of this: the dialog-cache +is probably not smart enough to hold multiple new styles, but with +the current mechanism you can add only one new style until you close the dialog. + +==== Keep track of current route style + +This is ensured via the `` selection in <>. + +At the end you are not drawing with the selected style, you are drawing +with a pen. When you change style, all parameters of the style +are copied into the pen. However, you can change any parameter of +the pen with hotkeys, which means you can easily end up drawing with a pen +that does not match any of the currently existing styles. + +Mainline has this too, it's all inherited. + +Using such a custom pen is useful when you want to draw a +single net of some special geometry - it is not worth adding a +new style, but you may still want to set the temporary pen up properly. + +The problem was that when you used such a custom pen, you didn't really +have a way to see your current setting and besides the `add +5 mils` kind of +hotkeys, you couldn't really set it up, e.g. +"I want 80 mil wide traces temporarily" +was hard to do. So I introduced the `` style, which shows the current +settings of the pen so it is not hidden anymore. + +NOTE: Lapsus here from Igor, who really means . I suggest to rename it ?? + +This way you can see and change all parameters of the pen, without having to +create a new style or having to use CLI actions. + +Igor2 definitely wants to keep `` in the gtk2 hid, wants to add it in the +lesstif hid and wants all new GUI hids to support it the same way. + + +`` mode is indicated by not selecting any style (no radio button selected). +As long as your pen matches any of the existing style, you are drawing with +that style and the style is marked in the radio button. +When you change your pen to something that doesn't match any existing style, +the radio button turns off. + +This is by design, Igor2 likes it, miloh, with whom we coded it likes it too. +Please do not change this. + +PCB Mainline does the same, except: + +* you can't see or modify the numeric fields of the `` style + directly (only modification possible is via hotkeys) +* you can't explicitly switch to the `` style (you need to make a + hotkey-modification of the pen) + +But the pen concept exists there too: press kbd:[Ctrl+Shift+V], it will change +the via drill size of the pen. This will result in a pen not matching +any existing style -> radio button selection disappears. + +=== PCB + +mainline has no explicit , no delete button and has the hardwired number of 4 styles. + +=== {prg} Next + +Honestly, I don't like it and want to change it (in all dialog boxes,even in gtk2): + +* I want the dialog boxes non-modal: you should be able to edit the layout while + the route style dialog is open +* I want changes to happen immediately - so if you change the line + width for a style and draw with it, it should have immediate effect +* I want to add undo code for the route style changes; I think the original + idea behind. Combining non-modal dialog and immediate effect makes cancel + meaningless, but if the user has the usual, central undo, that's fine. + +== GTK2 situation + +=== User manual + +Document this part... Most of the info are above. Select and create a section +-> See FIXME. + +Especially, document `Attributes` + +* what for ? +* expected key, values ? +* format ? units ? + +[[img-gtk2_gui]] +.{prg} on an empty design, with Edit Route Style dialog open +image::gtk2-pcb-rnd_001.png[] + +IMPORTANT: Where is `saved "as default"` ? Documentation here ? + +=== Short-term improvements ? + +This seems to be low priority w.r.t. cairo and GTK3... Am I right ? + +== GTK3 design proposal + +TODO: A mock-up (screenshot) + +A `GtkTreeView`, allowing the direct rename of style, allow sorting, or drag +and drop the styles to change order. + +Can be selected (highlighted) to show the active route style. + +`GtkButtonBox` with usual buttons : Add, Delete, Raise, Down ... + +Still another dialog is needed for other infos... + +== GTK2 retro-fit ? + +If so, then trade for a less advanced GtkTreeView + +`GtkHButtonBox` i.s.o `GtkButtonBox`. Index: tags/1.2.7/doc/developer/hid_gtk3/route_style.html =================================================================== --- tags/1.2.7/doc/developer/hid_gtk3/route_style.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_gtk3/route_style.html (revision 13657) @@ -0,0 +1,355 @@ + + + + + + + + +Route style GUI design + + + + + +
+
+

Abstract

+
+
+

This document is a WIP, working document, mixture of many sources of documentation +linked to the Route Style GUI part, as presented to the user.

+
+
+

PCB means PCB/gEDA, or mainline, pcb-rnd is the primary focus for this WIP.

+
+
+
+
+

1. Introduction

+
+
+

1.1. What is a Route Style

+
+

The Edit ▸ Route Styles menu allows you to select a style which is a group +of line thickness, via diameter, via drill size, and clearance (keepaway) +(collectively called a routing style) to be copied to the active sizes. +You can also change the names given to the routing styles and adjust their +values from Edit ▸ Route Styles ▸ Edit menu.

+
+
+

The active sizes are also adjustable from this menu (How ?). +The active sizes are shown in the status-line and control the initial size of +new vias, drilling holes, lines, clearances, text-objects and also +the maximum dimensions of the board layout.

+
+
+

A routing style can be attributed to a net. (How ?, How am I sure all the +nets/lines/tracks are affected to the selected routing style ?)

+
+
+
+

1.2. Using the autorouter

+
+

Do we still have the autorouter ? Is what is described next working elsewhere ?

+
+
+

Use routing styles in the netlist to have per-net routing styles. +Note that the routing style will be used for an entire net. +This means if you have a wide metal setting for a power net you will need to +manually route breakouts from any fine pitch parts on their power pins because +the router will not be able to change to a narrow trace to connect to the part.

+
+
+
+
+
+

2. Design intentions

+
+
+

2.1. pcb-rnd goals

+
+
    +
  • +

    Alleviate the limitation of 4 only different route styles.

    +
  • +
  • +

    Keep track of "current" route style

    +
  • +
+
+
+
+

2.2. pcb-rnd implementation prior 1.2.1

+
+

A radio-button area + extra dialog

+
+
+

2.2.1. Add a new route style

+
+

This is ensured via the <New> selection

+
+
+
+gtk2 edit route styles 001 +
+
Figure 1. Edit route styles dialog
+
+
+

Q: No Add button: historical reasons. The original code in mainline +has 4 route styles, hardwired. It can not remove styles. +We inherited the mechanism of adding style by selecting the <New>. +(In mainline if you add styles more than 4, they are lost on save).

+
+
+

The inherited code tries not to do modifications immediately but only when +you close the window. This is a common pattern in the gtk hid at the +moment: all data from core copied to some "hid_gtk-specific" mirror cache +for the dialog, then the dialog works on the cache and it is copied back +when you close the dialog.

+
+
+

Igor2 thinks the idea was that the dialogs are modal and if the user says +cancel, you just don’t do the copy-back. It’s a lot of extra code and complication. +The strange <new style> mechanism might be a result of this: the dialog-cache +is probably not smart enough to hold multiple new styles, but with +the current mechanism you can add only one new style until you close the dialog.

+
+
+
+

2.2.2. Keep track of current route style

+
+

This is ensured via the <custom> selection in dialog.

+
+
+

At the end you are not drawing with the selected style, you are drawing +with a pen. When you change style, all parameters of the style +are copied into the pen. However, you can change any parameter of +the pen with hotkeys, which means you can easily end up drawing with a pen +that does not match any of the currently existing styles.

+
+
+

Mainline has this too, it’s all inherited.

+
+
+

Using such a custom pen is useful when you want to draw a +single net of some special geometry - it is not worth adding a +new style, but you may still want to set the temporary pen up properly.

+
+
+

The problem was that when you used such a custom pen, you didn’t really +have a way to see your current setting and besides the add +5 mils kind of +hotkeys, you couldn’t really set it up, e.g. +"I want 80 mil wide traces temporarily" +was hard to do. So I introduced the <current> style, which shows the current +settings of the pen so it is not hidden anymore.

+
+
+ + + + + +
+ + +Lapsus here from Igor, who really means <current>. I suggest to rename it <current> ?? +
+
+
+

This way you can see and change all parameters of the pen, without having to +create a new style or having to use CLI actions.

+
+
+

Igor2 definitely wants to keep <custom> in the gtk2 hid, wants to add it in the +lesstif hid and wants all new GUI hids to support it the same way.

+
+
+

<current> mode is indicated by not selecting any style (no radio button selected). +As long as your pen matches any of the existing style, you are drawing with +that style and the style is marked in the radio button. +When you change your pen to something that doesn’t match any existing style, +the radio button turns off.

+
+
+

This is by design, Igor2 likes it, miloh, with whom we coded it likes it too. +Please do not change this.

+
+
+

PCB Mainline does the same, except:

+
+
+
    +
  • +

    you can’t see or modify the numeric fields of the <custom> style +directly (only modification possible is via hotkeys)

    +
  • +
  • +

    you can’t explicitly switch to the <custom> style (you need to make a +hotkey-modification of the pen)

    +
  • +
+
+
+

But the pen concept exists there too: press Ctrl+Shift+V, it will change +the via drill size of the pen. This will result in a pen not matching +any existing style → radio button selection disappears.

+
+
+
+
+

2.3. PCB

+
+

mainline has no explicit <custom>, no delete button and has the hardwired number of 4 styles.

+
+
+
+

2.4. pcb-rnd Next

+
+

Honestly, I don’t like it and want to change it (in all dialog boxes,even in gtk2):

+
+
+
    +
  • +

    I want the dialog boxes non-modal: you should be able to edit the layout while +the route style dialog is open

    +
  • +
  • +

    I want changes to happen immediately - so if you change the line +width for a style and draw with it, it should have immediate effect

    +
  • +
  • +

    I want to add undo code for the route style changes; I think the original +idea behind. Combining non-modal dialog and immediate effect makes cancel +meaningless, but if the user has the usual, central undo, that’s fine.

    +
  • +
+
+
+
+
+
+

3. GTK2 situation

+
+
+

3.1. User manual

+
+

Document this part…​ Most of the info are above. Select and create a section +→ See FIXME.

+
+
+

Especially, document Attributes

+
+
+
    +
  • +

    what for ?

    +
  • +
  • +

    expected key, values ?

    +
  • +
  • +

    format ? units ?

    +
  • +
+
+
+
+gtk2 pcb rnd 001 +
+
Figure 2. pcb-rnd on an empty design, with Edit Route Style dialog open
+
+
+ + + + + +
+ + +Where is saved "as default" ? Documentation here ? +
+
+
+
+

3.2. Short-term improvements ?

+
+

This seems to be low priority w.r.t. cairo and GTK3…​ Am I right ?

+
+
+
+
+
+

4. GTK3 design proposal

+
+
+

TODO: A mock-up (screenshot)

+
+
+

A GtkTreeView, allowing the direct rename of style, allow sorting, or drag +and drop the styles to change order.

+
+
+

Can be selected (highlighted) to show the active route style.

+
+
+

GtkButtonBox with usual buttons : Add, Delete, Raise, Down …​

+
+
+

Still another dialog is needed for other infos…​

+
+
+
+
+

5. GTK2 retro-fit ?

+
+
+

If so, then trade for a less advanced GtkTreeView

+
+
+

GtkHButtonBox i.s.o GtkButtonBox.

+
+
+
+
+ + + \ No newline at end of file Index: tags/1.2.7/doc/developer/hid_remote/Makefile =================================================================== --- tags/1.2.7/doc/developer/hid_remote/Makefile (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/Makefile (revision 13657) @@ -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/1.2.7/doc/developer/hid_remote/fixlab.sh =================================================================== --- tags/1.2.7/doc/developer/hid_remote/fixlab.sh (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/fixlab.sh (revision 13657) @@ -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/1.2.7/doc/developer/hid_remote/fixlab.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/developer/hid_remote/proto_high.html =================================================================== --- tags/1.2.7/doc/developer/hid_remote/proto_high.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/proto_high.html (revision 13657) @@ -0,0 +1,236 @@ + + +

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)

+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) +
+ +

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/1.2.7/doc/developer/hid_remote/proto_low.html =================================================================== --- tags/1.2.7/doc/developer/hid_remote/proto_low.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/proto_low.html (revision 13657) @@ -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/1.2.7/doc/developer/hid_remote/proto_parse.dot =================================================================== --- tags/1.2.7/doc/developer/hid_remote/proto_parse.dot (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/proto_parse.dot (revision 13657) @@ -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/1.2.7/doc/developer/hid_remote/proto_parse.html =================================================================== --- tags/1.2.7/doc/developer/hid_remote/proto_parse.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/proto_parse.html (revision 13657) @@ -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/1.2.7/doc/developer/hid_remote/proto_parse.svg =================================================================== --- tags/1.2.7/doc/developer/hid_remote/proto_parse.svg (nonexistent) +++ tags/1.2.7/doc/developer/hid_remote/proto_parse.svg (revision 13657) @@ -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/1.2.7/doc/developer/hid_render_comp.html =================================================================== --- tags/1.2.7/doc/developer/hid_render_comp.html (nonexistent) +++ tags/1.2.7/doc/developer/hid_render_comp.html (revision 13657) @@ -0,0 +1,109 @@ + + +

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 +
+ + + Index: tags/1.2.7/doc/developer/import.html =================================================================== --- tags/1.2.7/doc/developer/import.html (nonexistent) +++ tags/1.2.7/doc/developer/import.html (revision 13657) @@ -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 PCBType *. 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: +PCBType *PCB.). +

+In either case, PCBType's most important field is PCBDataType *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 DataType *buf which also have a PCBDataType *data containing +the same data a board could. +

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

    +
  • lists for layer-independent objects (e.g. rat lines, vias, elements) +
  • 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 LayerType 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 create.[ch]. +The functions that operate layer-independently usually get a destination as +PCBDataType, so they can operate both on boards and buffers. A typical +example is PinTypePtr CreateNewVia(DataTypePtr 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 LayerType *. A +typical example is LineTypePtr CreateDrawnLineOnLayer(LayerTypePtr 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 +
+ + +

Extra steps around creating a new board

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

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: +
+indent --line-length128 -brs -br -nce --tab-size2 -ut -npsl  -npcs -hnl -cli2 -ncs
+
+

+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 "sorrunding" lines to a largish patch, especially not in the +same patch/commit with actual code changes. + + + Index: tags/1.2.7/doc/developer/io_lihata_ver.html =================================================================== --- tags/1.2.7/doc/developer/io_lihata_ver.html (nonexistent) +++ tags/1.2.7/doc/developer/io_lihata_ver.html (revision 13657) @@ -0,0 +1,47 @@ + + + + pcb-rnd - io_lihata versions + + + + + + + + + + +
Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ + +

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. + + Index: tags/1.2.7/doc/developer/lihata_board/tree.lht =================================================================== --- tags/1.2.7/doc/developer/lihata_board/tree.lht (nonexistent) +++ tags/1.2.7/doc/developer/lihata_board/tree.lht (revision 13657) @@ -0,0 +1,169 @@ +ha:lht_tree_doc { + li: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:chidren { + 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 mm2}} + 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 } + 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 positin, X (horizontal)}} + ha:y { valtype=coord; obs=1; desc={last positin, 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 } + li:children { + ha:min_silk { valtype=coord; desc={Minimum silk width}} + + 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}} + 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:substrate { valtype=flag; desc={material: substrate or insulator}} + 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: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 } + 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={TODO}} + ha:objects { + type=li + {TODO: link line and describe simple objects} + } + } + } + } + } + } + } + } + ha:styles { + + } + ha:netlists { + + } + sy:conf = {/roots/conf} + sy:data = {/roots/data} + sy:attributes = {/roots/attributes} + } + } + ha:data { + + } + ha:conf { + + } + ha:attributes { + type=ha + desc { a hash of attribute key=value pairs } + li:children { + ha:attrib-key { valtype=string; desc={attribute value}} + } + } + } +} Index: tags/1.2.7/doc/developer/mods3/README =================================================================== --- tags/1.2.7/doc/developer/mods3/README (nonexistent) +++ tags/1.2.7/doc/developer/mods3/README (revision 13657) @@ -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/1.2.7/doc/developer/mods3/after.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/after.png =================================================================== --- tags/1.2.7/doc/developer/mods3/after.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/after.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/after.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/before.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/before.png =================================================================== --- tags/1.2.7/doc/developer/mods3/before.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/before.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/before.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/deps.svg =================================================================== --- tags/1.2.7/doc/developer/mods3/deps.svg (nonexistent) +++ tags/1.2.7/doc/developer/mods3/deps.svg (revision 13657) @@ -0,0 +1,893 @@ + + + + + + +plugin_deps + + +user + +user + + +acompnet + +acompnet + + +user->acompnet + + + + +autocrop + +autocrop + + +user->autocrop + + + + +autoplace + +autoplace + + +user->autoplace + + + + +autoroute + +autoroute + + +user->autoroute + + + + +boardflip + +boardflip + + +user->boardflip + + + + +dbus + +dbus + + +user->dbus + + + + +diag + +diag + + +user->diag + + + + +distalign + +distalign + + +user->distalign + + + + +distaligntext + +distaligntext + + +user->distaligntext + + + + +djopt + +djopt + + +user->djopt + + + + +draw_fab + +draw_fab + + +user->draw_fab + + + + +report + +report + + +user->report + + + + +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_nelma + +export_nelma + + +user->export_nelma + + + + +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 + + + + +fontmode + +fontmode + + +user->fontmode + + + + +fp_fs + +fp_fs + + +user->fp_fs + + + + +fp_wget + +fp_wget + + +user->fp_wget + + + + +gpmi + +gpmi + + +user->gpmi + + + + +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_lesstif + +hid_lesstif + + +user->hid_lesstif + + + + +hid_remote + +hid_remote + + +user->hid_remote + + + + +hid_srv_ws + +hid_srv_ws + + +user->hid_srv_ws + + + + +import_dsn + +import_dsn + + +user->import_dsn + + + + +import_edif + +import_edif + + +user->import_edif + + + + +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 + + + + +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_lihata + +io_lihata + + +user->io_lihata + + + + +io_pcb + +io_pcb + + +user->io_pcb + + + + +io_tedax + +io_tedax + + +user->io_tedax + + + + +jostle + +jostle + + +user->jostle + + + + +loghid + +loghid + + +user->loghid + + + + +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 + + + + +shand_cmd + +shand_cmd + + +user->shand_cmd + + + + +smartdisperse + +smartdisperse + + +user->smartdisperse + + + + +stroke + +stroke + + +user->stroke + + + + +teardrops + +teardrops + + +user->teardrops + + + + +vendordrill + +vendordrill + + +user->vendordrill + + + + +draw_csect + +draw_csect + + +draw_fab->report + + + + +draw_fontsel + +draw_fontsel + + +export_lpr->export_ps + + + + +export_xy->export_bom + + + + +fp_wget->fp_fs + + + + +hid_gtk2_gdk->draw_csect + + + + +hid_gtk2_gdk->draw_fontsel + + + + +lib_gtk_common + +lib_gtk_common + + +hid_gtk2_gdk->lib_gtk_common + + + + +lib_gtk_config + +lib_gtk_config + + +hid_gtk2_gdk->lib_gtk_config + + + + +lib_gtk_hid + +lib_gtk_hid + + +hid_gtk2_gdk->lib_gtk_hid + + + + +lib_gtk_common->lib_gtk_config + + + + +hid_gtk2_gl->draw_csect + + + + +hid_gtk2_gl->draw_fontsel + + + + +hid_gtk2_gl->lib_gtk_common + + + + +hid_gtk2_gl->lib_gtk_config + + + + +hid_gtk2_gl->lib_gtk_hid + + + + +hid_gtk3_cairo->draw_csect + + + + +hid_gtk3_cairo->draw_fontsel + + + + +hid_gtk3_cairo->lib_gtk_common + + + + +hid_gtk3_cairo->lib_gtk_config + + + + +hid_gtk3_cairo->lib_gtk_hid + + + + +hid_lesstif->draw_csect + + + + +hid_lesstif->draw_fontsel + + + + +lib_gensexpr + +lib_gensexpr + + +import_mentor_sch->lib_gensexpr + + + + +io_eagle->boardflip + + + + +io_kicad->lib_gensexpr + + + + +io_kicad_legacy->io_kicad + + + + +lib_legacy_func + +lib_legacy_func + + + Index: tags/1.2.7/doc/developer/mods3/export.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/export.png =================================================================== --- tags/1.2.7/doc/developer/mods3/export.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/export.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/export.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/feature.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/feature.png =================================================================== --- tags/1.2.7/doc/developer/mods3/feature.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/feature.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/feature.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/fp.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/fp.png =================================================================== --- tags/1.2.7/doc/developer/mods3/fp.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/fp.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/fp.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/gen.sh =================================================================== --- tags/1.2.7/doc/developer/mods3/gen.sh (nonexistent) +++ tags/1.2.7/doc/developer/mods3/gen.sh (revision 13657) @@ -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/1.2.7/doc/developer/mods3/gen.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/hid.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/hid.png =================================================================== --- tags/1.2.7/doc/developer/mods3/hid.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/hid.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/hid.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/import.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/developer/mods3/import.png =================================================================== --- tags/1.2.7/doc/developer/mods3/import.png (nonexistent) +++ tags/1.2.7/doc/developer/mods3/import.png (revision 13657) Property changes on: tags/1.2.7/doc/developer/mods3/import.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/developer/mods3/index.html =================================================================== --- tags/1.2.7/doc/developer/mods3/index.html (nonexistent) +++ tags/1.2.7/doc/developer/mods3/index.html (revision 13657) @@ -0,0 +1,501 @@ + + + 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: pcb-rnd version 1.1.3 +
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 + + +
acompnet75 + WIP + disable + feature + Auto-complete the current network. A very limited autorouter/assistant. +
autocrop158 + works + buildin + feature + Reduce the board dimensions to just enclose the elements. +
autoplace618 + works + buildin + feature + Automatically place elements. +
autoroute4361 + works + buildin + feature + Automatically route selected or all rats. This is the original autorouter. +
boardflip221 + +
(doesn't update rtrees) +
buildin + feature + All objects on the board are up-down flipped. +
dbus487 + WIP +
(needs to install the xml?) +
disable + feature + Remote control PCB using DBUS. +
diag211 + 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. +
distalign428 + 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. +
distaligntext467 + works + buildin + feature + Same as distalign, operates on text objects. +
djopt2334 + works + buildin + feature + Various board optimization algorithms. +
draw_csect537 + WIP + disable + feature + Draw cross section and layer map. +
draw_fab258 + works + buildin + feature + Draw the fab layer (for various exporters). +
draw_fontsel188 + WIP + disable + feature + Draw the font selector GUI +
export_bboard422 + WIP + disable-all + export + Export breadboard +
export_bom234 + works + buildin + export + Export bom (Bill of Materials) +
export_dsn455 + works + buildin + export + Export specctra .dsn files +
export_dxf3985 + WIP + disable-all + export + Export dxf +
export_fidocadj257 + WIP + disable-all + export + Export to FidoCadJ format (.fcd) +
export_gcode2476 + works + buildin + export + Export to gcode +
export_gerber1000 + works + buildin + export + Export to gerber +
export_ipcd356472 + Work-in-progress + disable-all + export + IPC-D-356 Netlist export. +
export_lpr108 + works + buildin + export + Export to lpr (using export_ps to generate postscript) +
export_nelma674 + works + buildin + export + Export to nelma (Numerical capacitance calculator) +
export_openscad1385 + WIP + disable-all + export + Export openscad +
export_png1118 + works + buildin + export + Export to png, gif and jpeg +
export_ps1645 + works + buildin + export + Export postscript or embedded postscript. +
export_stat269 + works + buildin + export + Export various board statistics in lihata format +
export_svg571 + works + buildin + export + Scalable Vector Graphics (SVG) exporter +
export_test261 + WIP + disable + export + A thin layer of code to dump exporter calls for testing the HID exporter API. +
export_xy276 + works + buildin + export + Export XY centroid element data for pick & place. +
fontmode266 + works + buildin + feature + Font editing actions. +
fp_fs389 + 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_wget570 + works + buildin + fp + Footprint: get static (file) footprints from the web, e.g. from http://gedasymbols.org +
gpmi3218 + works + buildin + feature + Scriptable plugin system with about 10 scripting languages supported and dynamic load/unload of scripts that can manipulate the GUI, the board, can implement exporters, etc. +
hid_batch319 + works + buildin + hid + HID without GUI: read actions from stdin. +
hid_gtk2_gdk1203 + works + buildin + hid + GUI: GTK2 HID with GDK software rendering. +
hid_gtk2_gl1638 + works + buildin + hid + GUI: GTK2 with opengl rendering +
hid_gtk3_cairo1005 + WIP + disable-all + hid + GUI: the GTK3 HID, using cairo for rendering +
hid_lesstif6994 + works + buildin + hid + GUI: the lesstif HID. +
hid_remote1174 + WIP + disable-all + hid + Remote access HID: implement a protocol and use it to relay between a core and a remote HID implementation. +
hid_srv_ws15 + WIP + disable-all + hid + HID server: websockets using hid_remote. +
import_dsn238 + works + buildin + import + Import specctra .dsn files +
import_edif3625 + works + buildin + import + Import plugin for netlists in the EDIF format. +
import_ltspice505 + works + buildin + import + Import the netlist and footprints from an ltspice .asc and .net pair of files +
import_mentor_sch493 + works + buildin + import + Import Mentor Graphics Design Capture from flattened .edf netlist, using a parts conversion table. +
import_mucs114 + works + buildin + import + Import lines and vias from MUCS unixplot .pl files +
import_netlist137 + works + buildin + import + Import plugin for netlists in the classic pcb netlist format. +
import_sch306 + works + buildin + import + Imports element and netlist data from the schematics (or some other source). +
import_tinycad148 + works + buildin + import + Import the netlist and footprints from a tinycad netlist. +
io_eagle940 + WIP + disable-all + io + Load the design from eagle's xml format. +
io_hyp3278 + works + buildin + import + Import plugin for hyperlynx geometry (no polygons yet). +
io_kicad3179 + works + buildin + io + Load and save the design and elements in Kicad's s-expression format - this is the new, currently preferred format in Kicad. +
io_kicad_legacy945 + works + buildin + io + Export the design and elements in Kicad's legacy format. +
io_lihata2268 + works + buildin + io + Load and save the design and elements in the lihata board format. +
io_pcb2349 + works + buildin + io + Load and save the design and elements in the original pcb text format. +
io_tedax686 + works + buildin + import + Import and export tEDAx netlists and footprints. +
jostle446 + works + buildin + feature + Pushes lines out of the way. +
lib_gensexpr10 + works + disable-all + lib + S-expression parser lib +
lib_gtk_common11405 + 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_config2679 + works + disable-all + lib + hid_gtk* preferences dialog common code (regardless of gtk version) +
lib_gtk_hid1380 + 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_legacy_func91 + 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. +
loghid273 + WIP + disable + feature + Sits between a HID (or exporter) and the core and logs all core->plugin calls made through the HID structure. +
mincut905 + 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. +
oldactions155 + 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) +
polycombine208 + works + buildin + feature + The selected polygons are combined together according to the ordering of their points. +
polystitch185 + segfaults + disable-all + 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. +
propedit773 + works + buildin + feature + List and edit properties of a group of objects. +
puller1889 + works + buildin + feature + Pull traces to minimize their length. +
query1835 + works + buildin + feature + pcb-rnd query language: execute expressions on objects and rules for the programmed drc. +
renumber309 + works + buildin + feature + Renumber elements (renaming them) and generate a text file for back annotation. +
report1021 + works + buildin + feature + Report() and ReportObject() actions - print a report about design objects. +
rubberband_orig904 + works + buildin + feature + The original rubberband code. +
shand_cmd212 + works + buildin + feature + vi-like command shorthands (1..3 character long commands) +
smartdisperse173 + works + buildin + feature + Improve the initial dispersion of elements by choosing an order based on the netlist, rather than the arbitrary element 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. +
stroke139 + partially works (doesn't work with lesstif, works with the gtk hid, but there's no zoom bindings) + disable + feature + Gesture recognition with libstroke. +
teardrops233 + 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 +
+ +

Plugin dependency map

+

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

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 +
+ +

Plugin dependency map

+

+pcb-rnd plugin dependency graph + + + Index: tags/1.2.7/doc/developer/mods3/pre.html =================================================================== --- tags/1.2.7/doc/developer/mods3/pre.html (nonexistent) +++ tags/1.2.7/doc/developer/mods3/pre.html (revision 13657) @@ -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: pcb-rnd version 1.1.3 +
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/1.2.7/doc/developer/new_model_progress/Makefile =================================================================== --- tags/1.2.7/doc/developer/new_model_progress/Makefile (nonexistent) +++ tags/1.2.7/doc/developer/new_model_progress/Makefile (revision 13657) @@ -0,0 +1,2 @@ +roadmap.svg: roadmap.dot + dot -Tsvg < roadmap.dot > roadmap.svg Index: tags/1.2.7/doc/developer/new_model_progress/roadmap.dot =================================================================== --- tags/1.2.7/doc/developer/new_model_progress/roadmap.dot (nonexistent) +++ tags/1.2.7/doc/developer/new_model_progress/roadmap.dot (revision 13657) @@ -0,0 +1,68 @@ +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] + + "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] + + 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} + + 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/1.2.7/doc/developer/new_model_progress/roadmap.svg =================================================================== --- tags/1.2.7/doc/developer/new_model_progress/roadmap.svg (nonexistent) +++ tags/1.2.7/doc/developer/new_model_progress/roadmap.svg (revision 13657) @@ -0,0 +1,272 @@ + + + + + + +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 + + +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/1.2.7/doc/developer/obj_func_naming.txt =================================================================== --- tags/1.2.7/doc/developer/obj_func_naming.txt (nonexistent) +++ tags/1.2.7/doc/developer/obj_func_naming.txt (revision 13657) @@ -0,0 +1,83 @@ +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_element_*_new(): + same as pcb_*_new(), parent being an element + + 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()) + + pcb_element_*_alloc(): + same, but parent is an element - will be removed once elements are + generalized. + + pcb_*_free(): + free the struct memory (but not the fields!) of an object and remove + it from the parent list. + + 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 + + +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/1.2.7/doc/developer/packaging.txt =================================================================== --- tags/1.2.7/doc/developer/packaging.txt (nonexistent) +++ tags/1.2.7/doc/developer/packaging.txt (revision 13657) @@ -0,0 +1,90 @@ +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 libgpmi is available. Since libgpmi is not +a mainstream library for the scripting feature it should also be packaged. + +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. + +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 (email +pcb-rnd (at) igor2.repo.hu) + +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/1.2.7/doc/developer/plugin_core_simple.html =================================================================== --- tags/1.2.7/doc/developer/plugin_core_simple.html (nonexistent) +++ tags/1.2.7/doc/developer/plugin_core_simple.html (revision 13657) @@ -0,0 +1,64 @@ + + +

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 Makefile, Plug.tmpasm and .pup from another, small plugin, for example from the report plugin (the next points will assume you picked this plugin as the source of the copy) +
  • 4. edit Makefile: replace report to plg +
  • 5. edit plg.pup; there should be short summary about the purpose of the plugin then "#key: value" pairs for statistics: +
      +
    • $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 +
    • $short short description - should be less than 32 characters; this shows up in the configure summary +
    • $long long description - used for documantation; no length limitation, but must be a single line +
    • $state either works or disabled +
    • $lstate [optional] a chance to explain why the value of default is what it is; e.g. why a plugin is disabled +
    • default disable-all or disable or buildin or plugin +
    • 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 excplicitly name it +
      + IMPORTANT: all fields are single-line, do not use semicolon (';') in any of the fields. +
    +
  • 6. edit Plug.tmpasm: +
    +put /local/pcb/mod {plg}
    +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/plg/foo.o $(PLUGDIR)/plg/bar.o @]
    +put /local/pcb/mod/CONF {$(PLUGDIR)/plg/foo_conf.h}
    +put /local/pcb/mod/YACC [@ $(PLUGDIR)/plg/bary @]
    +put /local/pcb/mod/LEX  [@ $(PLUGDIR)/plg/barl @]
    +		
    + +
      +
    • /local/pcb/mod: the name of the module we are compiling +
    • /local/pcb/mod/OBJS: a space separated list of object files to compile +
    • /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/YACC: optional: if you have files for yacc-processing, list them without the .y suffix here (space separated) +
    • /local/pcb/mod/LEX: optional: if you have files for lex-processing, list them without the .l suffix here (space separated) +
    • Leave the switch part on the bottom intact. +
    +
  • 7. create your C sources and headers in src_plugins/plg/ + The order of entries in the file is the same as the order in the summary table + at the end of ./configure; insert your plugin in the right group! +
  • 8. run "make map_plugins" in src/ to get your new plugin on the plugin list +
  • 9. run ./configure --buildin-plg +
  • 10. run make to see if it compiles and test +
  • (11. 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.) +
+ + + Index: tags/1.2.7/doc/developer/plugin_naming.html =================================================================== --- tags/1.2.7/doc/developer/plugin_naming.html (nonexistent) +++ tags/1.2.7/doc/developer/plugin_naming.html (revision 13657) @@ -0,0 +1,12 @@ + + +

pcb-rnd hacking - plugin naming conventions

+
    +
  • export plugins start with export_; these render to a non-native format that can not be then loaded +
  • native formats are 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_ +
  • interactive, often GUI, frontends are prefixed with hid_ +
  • footprint access plugins start with fp_ +
  • anything else is considered a feature plugin and has no specific prefix. +
+ + Index: tags/1.2.7/doc/developer/polygon.html =================================================================== --- tags/1.2.7/doc/developer/polygon.html (nonexistent) +++ tags/1.2.7/doc/developer/polygon.html (revision 13657) @@ -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/1.2.7/doc/developer/releasing.txt =================================================================== --- tags/1.2.7/doc/developer/releasing.txt (nonexistent) +++ tags/1.2.7/doc/developer/releasing.txt (revision 13657) @@ -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/1.2.7/doc/developer/renames =================================================================== --- tags/1.2.7/doc/developer/renames (nonexistent) +++ tags/1.2.7/doc/developer/renames (revision 13657) @@ -0,0 +1,1751 @@ +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_remve +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_remve +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 Index: tags/1.2.7/doc/developer/src/Makefile =================================================================== --- tags/1.2.7/doc/developer/src/Makefile (nonexistent) +++ tags/1.2.7/doc/developer/src/Makefile (revision 13657) @@ -0,0 +1,2 @@ +../data1.png: data1.dot + dot -Tpng $^ > $@ Index: tags/1.2.7/doc/developer/src/data1.dot =================================================================== --- tags/1.2.7/doc/developer/src/data1.dot (nonexistent) +++ tags/1.2.7/doc/developer/src/data1.dot (revision 13657) @@ -0,0 +1,59 @@ +digraph pcb_data { + PCBType_misc [label="misc fields:\nID\nName\nFileName\ncolors\ndrc settings\ncursor coords\ngrid\nlayergroups\nroute styles\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 [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_lists [label="layer-independent lists:\nrats\nvias\nelements\nsubcircuits"] + DataType_rtrees [label="layer-independent 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 + pcb_data_t -> DataType_LayerN + pcb_data_t -> DataType_layers + pcb_data_t -> DataType_lists + pcb_data_t -> DataType_rtrees + pcb_data_t [shape=box] + + DataType_layers -> pcb_layer_t + + + 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"] + + 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] + } + + LayerType_misc -> struct [style=invis] +} Index: tags/1.2.7/doc/devlog/20150731a_menu.html =================================================================== --- tags/1.2.7/doc/devlog/20150731a_menu.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150731a_menu.html (revision 13657) @@ -0,0 +1,60 @@ + + +

pcb-rnd devlog

+

Dynamic menus

+

by Igor2

+

Background

+Before integrating gpmi scripting, pcb-rnd needs to be prepared to +interface with the scripts. The engine is pretty much ready since ages: +the action interface is ideal for scripts to register their actions or +execute existing actions. This also means the command line and batch +UI are instantly connected with scripts. +

+The only largely visible remaining portion is the GUI. pcb-gpmi supports +building dialog boxes using the current HID (so called attribute dialogs, +originally invented for exporter settings) and calling some simpler predefined +dialogs like a progress bar or alert. +

+What's really missing is a way to create new menus on the fly. The user +loads a script and the script makes up a menu with submenus, all bound to +the proper actions. +

+This introduces a nice dilemma, tho: there is a real cool menu configuration +file that makes the user able to reconfigure the menu system, hot keys, tool +tips and whatnot (I wish more applications had this feature!). What if a script +comes in and trolls the whole thing creating random menus at surprising +places in the menu system? How the user can control what the script could do +with his preciously crafted menu setup tailored to his own preferences? +

+I believe in sharp tools and careful users. I indeed plan to allow scripts to +do whatever they want with the menu system but I invent some conventions too. +As long as scripts stick to these conventions, the user retain control over +the menu layout. + +

How it works

+ +PCB reads *menu.res and builds the gui on startup; the menu system is +static after that point. pcb-rnd does the same on startup but also +stores all menus (referenced by their paths, like "/File/Save as") in a +hash table. Later on a call to a new hid function (create_menu()) can +create new menus or submenus, extending the menu tree at any point. +

+When a new menu "/File/foo" is created, using the hash create_menu() +finds out that /File already exists and doesn't create it but use the +existing widget from the hash. This means if the user creates menus from +the res file that are also created by the script, the res file sort of +overrides the script's later actions as all those menus will already exist +by the time the script tries to create them. +

+And here comes the conventions part: +

    +
  • there will be a new menu, called "/Plugins" +
  • each plugin should have its own submenu there (gpmi for scripting: "/Plugins/GPMI scripting") +
  • each script is just a child of the gpmi plugin so it should have its submenus under "Plugins/GPMI scripting/scriptname" +
+ +As long as plugins and scripts stick to this convention, the user can +create all the menus for all the plugins and scripts in advance. Stock +menu res files will have the /Plugin menu at least, so its place is fixed. + + Index: tags/1.2.7/doc/devlog/20150731b_gtk.html =================================================================== --- tags/1.2.7/doc/devlog/20150731b_gtk.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150731b_gtk.html (revision 13657) @@ -0,0 +1,38 @@ + + +

pcb-rnd devlog

+

dynamic gtk menus

+

by Igor2

+

+As described in the previous post, +pcb-rnd will feature dynamic menus. I first implemented this in the +gtk hid. +

+It turned out gtk was way too OOP for my taste1. It took about 6 +hours total, to implement and debug the feature. (As a comparison, it +took about 90 minutes to make the research related to +the resource structs in PCB and implement the HID modifications for +the new hid command). The trickiest part was +to figure the need of calling a show() on the menubar after adding +the new items. +

+When I didn't have that, only plain action menu/submenus showed up +(in already existing menu/ widgets), but +new (main) menus and menu/submenu/submenus didn't. After many hours of gdb +sessions I finally made sure (by printing all the widgets to stderr +recursively) that: +

    +
  • I am really adding the new widgets... +
  • ... under the right parent +
  • ... with the right properties +
+Then I also printed allocated dimensions and coordinates - but the values +were misleading. Finally I figured there was different flags like realization +and visibility, so printed them too. This revealed that all my new menus were +there in an invisible state. +
+

Footnotes

+1: not because of the show() call, but because of the way objects +are stored in memory: too many generic pointers casted forth and back, makes it +really hard to print all properties of a menu item (including its label) +with gdb. Index: tags/1.2.7/doc/devlog/20150801a_events.html =================================================================== --- tags/1.2.7/doc/devlog/20150801a_events.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150801a_events.html (revision 13657) @@ -0,0 +1,24 @@ + + +

pcb-rnd devlog

+

events

+

by Igor2

+

+PCB has a nice action infrastructure: most user actions are +implemented in smallish functions taking (int argc, char *argv[]). Menu +items, hotkeys, the command line and batch processing just call these +actions. This is the user->pcb_core direction of commands. +

+Before adding scripting to pcb-rnd, the other direction (pcb_core->user) has +to be implemented: an event infrastructure. Random parts of the core +or the HID code will yield events using a simple vararg event() function. +Other parts of PCB, especially plugins, can bind (sign up to) events with +function pointers. When an event is triggered, all functions signed up to +the event are called (in random order). +

+Passing arguments to events is similar to the arguments of actions, except +argv[] is not a char *[], but an event_arg_t *[]. event_arg_t has an enum +field for argument type and an union for the argument value. This means the +API is binary: integers are passed as integers, not as strings. + + Index: tags/1.2.7/doc/devlog/20150803a_scriptig.html =================================================================== --- tags/1.2.7/doc/devlog/20150803a_scriptig.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150803a_scriptig.html (revision 13657) @@ -0,0 +1,38 @@ + + +

pcb-rnd devlog

+

scripting

+

by Igor2

+

+Most of the infrastructure for a scriptable pcb had been there in pcb-gpmi. +I had also finished some gpmi cleanup and pcb +(menu and + events ) subprojects last week. +These made it easier to get to reach the current status after a weekend +coding marathon: +

    +
  • dialog boxes for managing (loading/unloading) scripts -- check out the videos: + list scripts and get details or + load a new script + + +
  • import, test, extend the glue layer; scripts can: +
      +
    • register new actions +
    • create new menus and submenus +
    • execute existing actions +
    • pop up simple dialog boxes (message, report, progress bar, file selection) -- check out the video +
    • build and pop up custom dialog boxes (so called attribute dialogs) +
    • search for objects (lines, arc, polys, vias, etc.) on the layout +
    • create new objects on the layout +
    • change "page" properties (dimensions of the board) +
    • debug draw on the gui (slightly broken on gtk due to some gtk hid bugs) +
    +
+

+My example scripts are written in awk, lua and tcl +at this point, but gpmi supports 7 other languages +(scheme, stutter (lisp), pascal, perl +php, python, ruby) which are also available in +pcb-rnd. + Index: tags/1.2.7/doc/devlog/20150816a_scriptig.html =================================================================== --- tags/1.2.7/doc/devlog/20150816a_scriptig.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150816a_scriptig.html (revision 13657) @@ -0,0 +1,30 @@ + + +

pcb-rnd devlog

+

scripting, 2

+

by Igor2

+

+I've been working on the documentation for pcb-rnd scripting lately. +Proof reading and comments would be appreciated. The documents are +work-in-progress. +

+I have a Rosetta stone +of examples demonstrating how to write simple scripts. +It doesn't explain how the system works, but shows easy-to-understand +practical examples. Useful for those who like learn by doing and look up +the "theoretical" background only after seeing things in practice. +

+Another document, the +scripting intro focuses on explaining how things are built up. This +one is useful for those who first want to understand the design and then +look at how to do things in practice. +

+As a next step I plan to reorganize the package documentation and split +them all into a high level "what's the concept" doc and a low level +reference manual. +

+I also plan to improve the links between the docs and write more rosetta +examples. I plan to have a few more all-language examples on the most +basic things. The more complex examples would be written in awk, lua and +maybe ruby. + Index: tags/1.2.7/doc/devlog/20150820a_dimensions.html =================================================================== --- tags/1.2.7/doc/devlog/20150820a_dimensions.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150820a_dimensions.html (revision 13657) @@ -0,0 +1,26 @@ + + +

pcb-rnd devlog

+

fp2anim dimensions

+

by Igor2

+

+After attacking the qfn()/qfp() parametric footprint problem today, +I realized fp2anim lacked a very important feature: dimension lines. +The footprint being generated is to match the datasheet. Checking the match +requires visible dimensions. +

+The new feature of fp2anim is to optionally display custom dimensions on +the preview. Generator scripts print #dimension comments in the footprint +file (not breaking the file format). The generator passes on a dimension +name along with the value. As a first attempt my conventions are: +

    +
  • add dimension lines for dimension type input parameters +
  • add dimension lines for calculated dimensions if they are likely to be informative and be included in the datasheet +
+ +

fp2anim vector font

+While working on the dimensions, I realized I had to switch to vector fonts: +the built-in pixel font of animator can not be rotated. The size of a vector +font text can be calculated, which also enables fp2anim to optionally place +semi-transparent bars behind the text to make it more visible on dark background +(like pads). Index: tags/1.2.7/doc/devlog/20150820b_qf.html =================================================================== --- tags/1.2.7/doc/devlog/20150820b_qf.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150820b_qf.html (revision 13657) @@ -0,0 +1,29 @@ + + +

pcb-rnd devlog

+

qf()

+

by Igor2

+

+The next group of footprints I decided to generate are qfn(), tqfp(), lqfp(). +The generic set of rules for these footprints is: +

    +
  • there is a virtual rectangle that forms rows of pads +
  • pads are evenly spaced among the edges of that rectangle +
  • pin numbering is counter-clockwise +
  • the body of the part may be inside of the rectangle or may extend over the pads +
+ +

low level flexibility vs. high level comfort

+qf() currently has 14 arguments. It is flexible enough to generate qfn, tqfp, +lqfp, and anything similar I've seen in the package datasheet of a major +vendor. However, it is not straight forward to convert datasheet tables +into qf() parameters. +

+On the other hand, in practice we need qfn() and tqfp(), which are special +cases of qf(). To nail the common use cases, qfn() and tqfp() narrows down +the number of parameters to 3..4. Even better, these parameters are exactly +those that are in the name of a typical QFN or TQFP footprint or in the first +few lines of the dimensions table. I call these scripts frontends to qf(). +

+This makes the common footprints very easy to produce using frontends while +leaves a (bit more complicated) plan B, qf(), for special cases. Index: tags/1.2.7/doc/devlog/20150821a_parametric_requirements.html =================================================================== --- tags/1.2.7/doc/devlog/20150821a_parametric_requirements.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150821a_parametric_requirements.html (revision 13657) @@ -0,0 +1,33 @@ + + +

pcb-rnd devlog

+

requirements for parametric footprint generation

+

by Igor2

+

+It's appealing to write parametric footprint generators for new footprint +families: invest some time once, and have a tool that can spit out +dozens of footprints. However, it is not always worth having a generator +instead of static footprints. The minimal requirements for a generator are: + +

    + +
  • the footprint family is a series of footprints that can be generated +using the same code, with changing some base properties (e.g. number of +pins) + +
  • dimensions and other properties can be calculated from the base +properties with reasonable formulas and conditional code; e.g. sot* is not +a good candidate for generation, as sot23 or sot89 can not be generated +from some common ancestor by varying one or two parameters, but would need +a large table that translates package name to a pattern - easier to keep +those in static footprint files + +
  • has a reasonable amount of existing variations; e.g. it is not worth +writing a generator for the dsub family because there are only a few of +them in common use (db9, db15, db25, and maybe db37). + +
  • preferably a link to a datasheet that shows at least 3 members of the +family; if that's not possible, separate datasheets describing at least 3 +members of the family. + +
Index: tags/1.2.7/doc/devlog/20150830a_fork_faq.html =================================================================== --- tags/1.2.7/doc/devlog/20150830a_fork_faq.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150830a_fork_faq.html (revision 13657) @@ -0,0 +1,248 @@ + + +

pcb-rnd devlog

+ +

Fork FAQ

+

by Igor2

+

+ +This document contains my short answers to questions commonly popping up +in endless flamewars on the geda mailing list. The purpose of this +document is not to convince anyone about any of the questions, only +to save me some time typing the same answers when someone asks me +one these questions for the 100th time. As I don't want to convince you +that my answers are the best ones, please don't try to convince me that +they are bad. Been there, done that, never worked in either way: e.g. +I never convinced any git fanboy to switch to svn, and they never +convince me to switch to git. + +

1. Why did you fork?

+ +

1.1. Fragmentation is bad, your fork is harmful!

+I agree that fragmentation is bad. I believe the same aspects of +the current project management and especially the choice of VCS inevitably +leads to forks (just look at how many git forks are out there!). Such +fragmentation of developer and user resources may be bad for a project. +However, these decisions are not mine: the project is set up like +that, I can't change it +

+My fork is just a fork, just like any of the other forks. My fork happens to +be in an svn repository. I don't think it changes anything important from the +mainline's point of view. + +

1.2. ... but how will you get all these merged with mainline?

+I won't. I haven't really used the official, current mainline since like +2011. I don't really care in what directions it evolves or whether it +takes features, code or ideas from pcb-rnd or not. + +

1.3. ... but you are in the best position for a merge!

+I don't think so. I know my changes, but I don't know the changes happened +in the mainline since ages. I am also not efficient with git. It wouldn't +take me any less time than for mainline developers. Also please read point 1.2.: +I have no motivation in spending any time on a merge. + +

1.4. Ok then, but you won't have too many users.

+Fine. My main intention was to produce a pcb editor for my own use. I am +happy if it's also useful for others, so I publish it. Having users +may increase code quality - but other than that, I don't get paid for having +more users, the project doesn't die if I code it alone, so I am not worried +about this. +

+Update (Aug 2016): an active user/contributor community is forming +around pcb-rnd. It is not a one-man-show anymore. + +

1.5. I'd like to merge something from pcb-rnd to mainline

+Go ahead. I can help you by explaining my code. I won't generate +patches, make changes to get my code compatible with the mainline or +test how it performs in mainline versions. + +

1.6. I'd like to merge something from mainline to pcb-rnd

+If the feature is in line with the goals of pcb-rnd, fine, I'll give +you svn commit access from day 0. + +

1.7. Would you abandon the development of pcb-rnd and join the mainline, if...

+Unlikely. There are many things I have in pcb-rnd which I believe won't ever +happen in mainline. There are a few which I find critical: if I'd need to +give up any single item from this list, that would be a deal-breaker for me: +
    +
  • simple, centralized VCS (not just the UI, the whole thing) +
  • VCS based, zero-administration release and publish interface +
  • a sane build system instead of autotools +
  • the code won't switch to C++ +
+ + +

1.8. Would you join the development of gschem?

+Unlikely. See point 1.7. Gschem is not aiming to a C++ transition AFAIK, +but has a lot of scheme. I don't consider joining or contributing to +gschem until those points listed in 1.7. are fixed and a new scheme +policy is introduced. The new policy should be: "from now on +do not write new code in scheme, use C; while making changes and fixes, +convert affected scheme code to C. Long term, explicit plan: convert all +scheme code to C and remove the guile dependency." +

+I don't expect any of this to happen. +

+Update (Aug 2016): Instead, I'll launch cschem . + + +

2. git: did you know...

+ +Preface: I don't try to convince you not to use git in your project; in +return, please don't try to convince me I should use git in mine. + +

2.1. ... that there was an svn frontend to git?

+Yes. 2/3 of my problems with git and DVCS in general are not of technical +nature. I know the concepts of DVCS and I find them suboptimal in +case of small teams. A different UI or a good document won't help in that. + +

2.2. ... that there was this great document about git?

+See 2.1. + +

2.3. ... that DVCS is the future, anything centralized is bad, svn is obsolete?

+These are not facts, but slogans I don't believe in. + +

2.4. What if someone has to develop offline for long?

+In the 21th century, when we have cheap mobile internet even in eastern +Europe? + +

2.5. But feature X is harder with svn!

+Almost all those features are bad for team work in my experience. They +are not even needed. Yes, some aspects of the development have to be +done differently without those - but this is good for the project. + +

2.6. But there are no local repositories and you have to commit unfinished stuff and worry if anything breaks! And branching is hard

+This is the point. I do not branch. I do not attempt to work offline for long, +whatever technical support the VCS may provide for that. I try to work in +a team, on a common code base. +

+I commit small things. I make sure I do a big transition using +these small commits in a way that the code stays compilable in between any +two commits. It rarely breaks trunk/ for longer than a few minutes. I +need a real branch once a decade. + +

2.7. But that's extra effort and makes life harder!

+Yes and no. It's certainly harder to design and carry out a big +reorganization in small steps. This is an extra cost. However, the +benefits outweigh this: everyone working in the same repo, +other developers see and comment what you are working on, if done right, +merging is nearly never needed and conflicts are as rare as bugfree +release of a multi-million line proprietary software. + +

2.8. I don't agree with any of this, git is better!

+Cool, so go on using git. I didn't try to convince you not to, I just +explained why I won't. + +

3. opengl

+
+

3.1. But I need opengl!

+Use the mainline then. Or contribute the code for sane opengl support +in pcb-rnd. +

+Update (Aug 2016): GUI HIDs are plugins now, multiple GUIs can +be compiled and chosen run-time. Default GUI is a runtime configuration too. +All we need to have an opengl GUI HID now is a gl-capable volunteer. +

+Update (Mar 2017): thanks to our great contributors, the gl issue +is solved now - both gl and gdk rendering GTK hids are available now, for +runtime HID selection. + +

4. programming languages, file formats

+
+

4.1. switch to C++, it is so much better

+Nope. I prefer C. + +

4.2. but pcb-rnd doesn't compile with a C++ compiled

+Correct: pcb-rnd is written in C. It also doesn't compile with a Pascal +compiler. + +

4.3. but mainline already invested in preparing a C++ transition

+Good for them. If I didn't have a fork, I'd fork the day when the first +C++ class is committed. + +

4.4. we need SQL for the file format

+No, we don't. I prefer human readable text formats. No, converters won't +solve that. No, I don't care if python has support for loading SQL files. +

+Update (Aug 2016): the file format is a replaceable plugin now; +it's even possible to have multiple alternative formats active in the same +time. It's up to you to implement your format in a plugin. + +

4.3. we need to switch to xml/json (or python or perl arrays)

+No, we don't need to. +

+Update (Aug 2016): ... unless you implement it in a plugin, see point 4.4. + +

4.4. ... but they are easier to parse because of existing libs

+Yup, but in any real life task that part of the parsing is like 5%. The +rest 95% needs to be programmed anyway. The costs of such a file format change +is not justified by this minor gain. + +

4.5. ... but the current file format doesn't support feature X

+ +True. And that's because the internal model (the in-core representation +and all the code handling that) doesn't support the feature either. +Changing the file format won't help that. It's similar to point 4.4.: 95% +of the effort is needed to get the code to support the feature, and by that +time the cost of getting it into the file format is very small. Costs +are not justified. + +

+Update (Aug 2016): long term the new primary file format will be +lihata to overcome the above limitations. Later on the internal representation +may change too. + +

4.6. ... but I can't build a database of the current lib

+Too bad. Either figure how to do it, or just don't do it. pcb-rnd +offers scripting, even in languages that have SQL support. In theory +it wouldn't be that hard to write scripts running in PCB manipulating +the buffer or even the in-core footprints on one end and connecting +an SQL database on the other end. + + +

5. scconfig, autotools, build systems

+
+

5.1. scconfig doesn't support feature X that autotools does

+Are you sure? Maybe it does, just uses a different syntax. If not, did +you try to send me a feature request? + +

5.2. scconfig's syntax is different

+Yes. Scconfig has a totally different internal model thus the UI differs +too. Same as vim has a different UI than emacs, while they are both text +editors and the two communities are not trying too hard to unify the UIs. + +

5.3. But ./configure has to have the same UI as autotools

+False. + +

5.4. Most people know autotools, there are merits in supporting the same features or UI

+I do realize that. I've been working on scconfig since 2008. I've invested +a lot of time in it. Believe me, I did think it over before I decided that +the benefits would overweight the drawbacks of developing/using a custom +config/build system. + +

5.5. But autotools is so much better!

+No, it isn't. My experience is that with random open source projects +on anything different from Linux, modern BSD, and sometimes windows, it +just breaks at least 8 times out of 10. Try it once on IRIX or minix. + +

5.6. So why don't you rather fix autotools?

+I believe there are multiple design problems in autotools and most of +the practical problems I faced when using it were directly caused by those. +In a sense, I did fix these design problems by using a different design. +The different design is called scconfig and it was much easier to +write it from scratch. + +

5.7. But scconfig doesn't do cross compilation!

+False. It does. It's been supported since May 2008. It's been added +about 1.5 months after the very first file. +

+Update (Aug 2016): as a practical example, windows .exe has +been cross-compiled on a Linux box. + +

5.8. I just don't like scconfig.

+If you have something particular that makes you dislike scconfig, +a missing feature for example, please let me know. +

+Else maybe you don't like using anything else than autotools. It's your +choice; mine is that I do keep on using scconfig in my projects. + Index: tags/1.2.7/doc/devlog/20150830b_back_ann.html =================================================================== --- tags/1.2.7/doc/devlog/20150830b_back_ann.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150830b_back_ann.html (revision 13657) @@ -0,0 +1,305 @@ + + +

pcb-rnd devlog

+ +

back annotation

+

by Igor2

+ +

netlists, annotations

+ +Pcb-rnd (and mainline pcb) maintains a netlist as part of the design. Pcb +doesn't modify the netlist. The netlist is imported from an external source, +typically from gschem. This process is called forward annotation. +

+Sometimes there are a set of connections which contain pin pairs that could +be swapped. For example the data lines of an external parallel SRAM interface +to an MCU: it doesn't matter if data bit 1 at the MCU is wired to data bit +1 or 5 of the SRAM, as there is an 1:1 mapping and no one else is using the +same bus wires. In this case connections should be swapped during pcb routing +and annotated back to gschem so that the schematics can be updated. Both +paths are illustrated below. +

+annotation paths +

+Forward annotation passes on complete netlists along arrows forward1 and +forward2. Back annotation would pass back netlists, changes or modification +requests on the back1, back2 path. Gnetlist takes sch files to extract +and build a netlist in whatever format the receiver needs. There should be a +glue layer, called foo on the drawing, that does the reverse: receives +whatever format the sender has and generates something that gschem will +understand. + +

Support in pcb-rnd: core

+Pcb-rnd gets a complete netlist. If the user could change the netlist directly, +there should be some sort of diff tool in foo that can explain the +changes to gschem, or a diff tool in gschem. What is worse, forward annotation +happens much more often than back annotation and pcb-rnd would need to be able +to merge a new netlist with local changes. The simple "gsch2pcb overwrites the +netlist in pcb from whatever gnetlist produced" approach would not work. +

+An alternative is to keep the netlist as-is, and maintain a separate list of +changes. The form proposed hereby is a table of "operation,pinID,net" or +"operation,args...". Netlist operation is one of "del_conn", "add_conn" and "net_info". The table is called the netlist patch. +

+For example assume two components with pins A1, A2 and B1, B2, with connections +n1=A1-B1 and n2=A2-B2. While routing the designer decides changing them to +n1=A1-B2 and n2=A2-B1 would be easier and is acceptable by the design. The +table of changes would contain this: + +
op pinID net +
del_conn B1 n1 +
del_conn B2 n2 +
add_conn B2 n1 +
add_conn B1 n2 +
+The first two lines would remove pins B1 and B2 from n1 and n2. The last +two would put them back, swapped. New nets could be created or unused nets +could be removed using the add_net and del_net commands that have empty pinID. +The table is ordered, rows are strictly executed from top to bottom. +

+Pcb-rnd would store this table in memory. When some code calls the netlist +code to find out the members of a net, or which net a given pin is connected to, +after running the original netlist code, the result would be adjusted by the table. +

+The table would be normalized after operations. For example: + +
op pinID net +
del_conn B1 n1 +
add_conn B1 n2 +
add_conn B1 n3 +
del_conn B1 n2 +
+would be reduced to + +
op pinID net +
del_conn B1 n1 +
add_conn B1 n3 +
+Simple linear crawls on the table seems sufficient: it is expected that +pcb designers will make netlist modifications rarely and they will back +annotate them ASAP. In extreme cases there may be 64 bit wide bus systems that +need total reordering; even a 4 such reorders will introduce about 1024 items +on the list which seems not too big for O(1) algorithms. See section TODO +for better approaches. +

+Pcb-rnd would save the normalized table in the pcb file in a new section. +Upon a netlist change in pcb (import/load netlist or load the pcb), pcb-rnd +would check each row of the table: it is easy to decide whether that row +has been implemented in the netlist or not. Obsolete rows of the table would +be deleted. +

+A corner case is when B1 is removed from n1 and then added to n2 by the table, +while a new forward annotation removes B1 from n1 and adds it to n3. In this +case the first row of the table is deleted, as B1 is already removed from n1, +but pcb-rnd has no chance to decide if netlist adding B1 to n3 should affect +the table adding B1 to n2, so that rule is kept. +

+net_info is used to describe the original members of a net, in +the state they were before any change on the netlist occurred. + +

Support in pcb-rnd: GUI

+A trivial idea is to extend the netlist window so that pins can be moved in +between nets or deleted or assigned to nets. Changes should be marked. This +is not the preferred way of editing the netlist, tho: not much more convenient +than making changes in gschem and doing forward annotation. +

+There should be a separate dialog box or a separate region of the netlist box +showing the netlist patch with edit capabilities. +

+Finally, the most important feature would be new actions resolving shorts. +Using the above example (n1=A1-B1 and n2=A2-B2 changed to n1=A1-B2 and n2=A2-B1), +I believe the user would: + +
action screenshot patch list after the actions +
  • look at initial rats
(empty) +
  • first connect A1 to B1
(empty) + +
    +
  • then realize it's very hard to connect A2 to B2 while the previous connection is there +
  • he would then revert the first connection +
  • and connect A1 to B2 +
  • which would cause shorts +
+ (empty) + +
    +
  • then he would use the "approve netlist change" hotkey/action on the network; + this would add netlist patch commands for the A1-B2 connection, + but would also keep the A1-B1 connection, which remains a rat; because + of the new connection there'd be a rat between A1 and A2 or B1 and B2 too + (all 4 pins connected together on the patched netlist at the moment!) +
+ +
+net_info n1 A1 B1
+net_info n2 A2 B2
+del_conn B1 n1
+add_conn B1 n2
+
+ +
    +
  • the user would then use an action (maybe the same one?) on the rat line + so that pcb-rnd would understand that rat is not needed anymore and + would add a patch to remove the A1-B1 connection +
  • the same thing would need to happen to the A2-B2 rat +
+ +
+net_info n1 A1 B1
+net_info n2 A2 B2
+del_conn B1 n1
+add_conn B1 n2
+del_conn B2 n2
+
+ + +
  • the user then would connect A2 to B1, which again is a short
+
    +
  • the user would approve it as a new connection +
  • we have exactly 2 del_conn and 2 add_conn patches. +
+ +
+net_info n1 A1 B1
+net_info n2 A2 B2
+del_conn B1 n1
+add_conn B1 n2
+del_conn B2 n2
+add_conn B2 n1
+
+ +
+An experienced user may think a few steps in advance and +chose to first remove the A1-B1 and A2-B2 rats and then create the A1-B2 +and A2-B1 connections and then approve the two new connections. +

+An alternative is drag&drop ratline endpoint onto snap points; it may +be tricky to convert that to net/pin relations if a rat line is between two +line segments, tho. +

+These changes would live immediately, leaving the board free of shorts and +rats. There should be, however, some warning in the "congratulation" message +that tells the user a back annotation is still required. + +

Support in gschem

+Ideally there should be a very small change in gschem and an optional +plugin script could do the rest. The plugin script would be in contant +with foo. +

+There are multiple ways pins can be connected to a net in gschem. It's +probably not a good idea to have too much automatism in the gschem's side, +trying to actually removing connections and adding new ones using the patch +(or whatever info foo converted the patch into). +

+However, gschem should support four things natively: +

    +
  • it should have a concept of an unwanted pin-network connection; a connection + becomes unwanted only when the back annotation says so +
  • it should be able to mark unwanted connections on the active schematic page +
  • it should be able to tell the user if there are unwanted connections on + any of the pages open +
  • it should be able to refresh its idea of unwanted connections while + schematic pages are open +
+

+Displaying unwanted connections happen at: +

    +
  • a pin of a component is connected to a net using a "blue line" net: mark the pin-net connection point +
  • a pin is directly connected to another pin, no net line in between: mark the connection point +
  • a pin is connected to a net using a pin attribute: mark the pin +
  • TODO: are there more? +
+

+TODO: there are a lot to think over about special cases related to +multipage schematics, hierarchies, slots, split symbols. + +

What foo does exactly

+... is not clear yet. It depends on what sort of support gschem would provide. + +

Amendment 1: other parameters (1st sep)

+I originally forgot to mention my other intentions in the above document: +back annotate non-netlist properties. It probably happened because netlist +related stuff are the hardest to solve. +

+There are other parameters that sometimes change during routing. A common case +for my 1 or 2 layer boards is when I originally intend to use 0603 parts but +during routing I figure I need to pass a trace between the pads. I need to +change the part to 0805 or 1206 (for two traces). I'd like to be able to +do this in-place in pcb with an action that replaces the footprint +but keeps the origin in place. This obviously still requires some manual +fiddling afterwards, but would remove the long, tedious chain I have now: +

    +
  • 1. remember or note down which parts to change footprints for +
  • 2. go back to gschem and change them +
  • 3. get the changes in pcb (I use gsch2pcb and Makefiles, one step; the import menu is one step too, just another one) +
  • 4. disperse the new elements +
  • 5. find where they used to be +
  • 6. and then do the fiddling to fit them in +
+

+The new process would be: +

    +
  • 1. get the footprint replaced, in-place; this would already approve the + change and there'd be a command for it in the patch table +
  • 2. do the fiddling to fit the new part in +
  • 3. do a back annotation +
  • (4. optionally, if we go for non-automatic change of attributes in gschem, + change them manually in gschem, cycling through the affected + items using some UI feature) +
+

+The same thing could work for values, which is the other attribute PCB also +sees. The same mechanism could work from other programs as well, e.g. tuning +the values of some parts in a simulator and then back annotating the changes +to the schematics. The patch table format foo handles would be in the +simplest plain text form. + + +

Amendment 2: examples from gschem's point of view (3rd Sep)

+

netlist change

+
    +
  • The user creates the schematics and imports it in pcb; the original + netlist contains a line "netname1 U1-1 CONN1-2" +
  • The user, as part of some pin swapping, decides that U1-1 should be + connected to net "netname2" instead of "netname1". Changes are + done in pcb-rnd as described above. +
  • The netlist patch generated for this single change by pcb-rnd would be: +
    +del_conn netname1 U1-1
    +add_conn netname2 U1-1
    +	
    +
  • the user may need to load the netlist patch in gschem +
  • In gschem there would be an indication that highlights any U1-1 pin or + U1 symbol that makes a connection to netname 1, graphically or using + attributes. When asked, gschem UI would also tell the user that U1-1 is + now connected to netname1 but should be connected to netname2 instead. +
  • The user would find this indication and would resolve the situation + by whatever changes he finds appropriate +
  • gschem would rerun the patch commands and would figure that the del_conn + fails to run because U1-1 is no longer connected to netname1 and the add_conn + fails too because U1-1 is connected to netname2. This leaves U1-1 without + any known issue, so the indication on U1-1 would be gone. +
+ +

attribute change: footprint change

+
    +
  • The user creates the schematics and imports it in pcb; originally + U1 has an attribute footprint=DIP(8). +
  • during the layout the user figures using the footprint SO(8) is + more appropriate. He does the change in pcb-rnd. +
  • pcb-rnd emits the following netlist patch for this: +
    +change_attrib U1 footprint=DIP(8) footprint=SO(8)
    +	
    +

    + (or it could be a del_attrib and add_attrib pair, like with connections) +

  • the user may need to load the netlist patch in gschem +
  • In gschem there would be an indication that highlights any U1 instances + that has footprint=DIP(8) +
  • The user would find this indication and would resolve the situation + by whatever changes he finds appropriate (e.g. change the attribute) +
  • gschem would rerun the patch commands and would figure the change is + no longer required and would remove the indication +
+ Index: tags/1.2.7/doc/devlog/20150901a_back_ann.html =================================================================== --- tags/1.2.7/doc/devlog/20150901a_back_ann.html (nonexistent) +++ tags/1.2.7/doc/devlog/20150901a_back_ann.html (revision 13657) @@ -0,0 +1,88 @@ + + +

pcb-rnd devlog

+ +

back annotation

+

by Igor2

+ + +

Conclusions of the first thread

+DJ has another
model +where back annotation is only a subset of a bigger mechanism. +

+Many other users commented the thread, but no one else presented a +plan that formed a complete system. +

+While there were some useful feedback about some details, no one explicitly +said he'd be contributing the gschem part (... for any of the ideas floating +around). +

+The thread is swamped in a chaotic set of random ideas and opinions - the +same way as previous related threads usually did. + + +

Second thread

+In the second thread I will focus on actual contribution. For this, +I'm narrowing down what exactly needs to be contributed: + + +
    +
  • 1. minor UI changes, most probably in the C part of the gschem code. +somehow ending up in the official repo; I'd prefer to avoid maintaining a +fork of gschem (no, having the fork in git doesn't help). + +
  • 2. a scheme script that can be plugged into gschem and do real simple +things like toggling flags for point 1, counting how many flags are +toggled, warn the user about the counter is being non-zero; this script +doesn't need to get into the official repo + +
  • 3. depending on whether we (me and my actual contributor who contributes +code) go for push or pull, we need: a new action or menu or whatever that +can trigger a pull or some means that can collect a change list pushed and +then indicate that something's happened. It's not really a third piece of +code, just a third piece of concept that is spread across 1 and 2. +
+

+First, I seek a contributor for exactly these 3 things. Alternatively if +there's someone who is really willing to contribute actual code and spend +time on this, I'm open to change parts of my plan if he has better ideas +as long as the new approach still solves the actual problems I have. + + +

Preparing for the third phase (3rd sep)

+Options are being eliminated slowly. I couldn't find out who are currently the +maintainers of gschem, so I couldn't ask their opinion about my back annotation +plan directly. Last stable release is about 2 years old, last unstable is more +than a year old. +

+The main options currently are: +

    +
  • 1. Evan offered contribution on the gschem side; Markus offered him write + access to the official git repo. We could have a branch there. We'd + aim for a merge, so minimal changes and a lot of scheme hacking (... + that still none of us want to do, afaik). + Without positive feedback from maintainers, I believe this branch + has a very low chance to get merged in mainline. If it doesn't get + merged, all the extra effort on scheme, git, and trying to + do things in the gschem-way are just energy wasted. + +
  • 2. I start an svn repo and implement the stuff the better way (no + scheme, bigger change, no worries about whether it gets merged). Keep + changes on-topic and small, so later on if someone wants to merge, + there's a chance to get it into a branch in the git repo first then + do the merge. Has even lower chance to get merged, but certainly + speeds up development and is much easier to work on, distribute and + use than a bitrotting git branch. If it doesn't get merged, + only a small amount of efforts wasted on trying to keep changes + merge-friendly. + +
  • 3. I start an svn repo and implement the stuff the best I can - without + considering any merging aspects. This is the option that'd grant + the most development speed and efficiency. It doesn't get merged, + but no energy is wasted at all and the resulting code is better. +
+There are some other options, but those are just variants of the above three. +Currently I think option 1 is unlikely to work, for I don't touch git, +and noone wants to touch scheme. Both 2 or 3 could work, but the total lack +of gschem maintainer feedback doesn't make option 2 look too good. + Index: tags/1.2.7/doc/devlog/20151028_glib.html =================================================================== --- tags/1.2.7/doc/devlog/20151028_glib.html (nonexistent) +++ tags/1.2.7/doc/devlog/20151028_glib.html (revision 13657) @@ -0,0 +1,66 @@ + + +

pcb-rnd devlog

+ +

why glib is a bad idea

+

by Igor2

+

+Levente tried to compile pcb-rnd on bsd and used a different c compiler +than gcc. For this in the first step I fixed the build system so that it +doesn't have gcc --std=gnu99 but gcc --std=c99. +

+And then everything broke. A minilib I use for hashing, +genht, failed to +link against hid/common/action.c. I first thought it was a bug in genht: +genht was compiled without --std while the rest of the code compiled with +--std=gnu99 or --std=c99. Genht heavily depends on static inline +functions for performance, maybe that's why. +

+So I tried to reproduce the situation in a hello-world like program and +tried all combination of --std, -DNDEBUG, -rdynamic and all build flags +used in pcb-rnd for the genht lib and the test program, but all combination +worked. It looked like it broke only in pcb-rnd. +

+I gave up on the minimal test case and went back to pcb-rnd. I realized if +the build is the same, the only way it may break is that some header +included before genht's headers change some global state. I started to +shuffle the #includes. Long story short, it turned out if <glib.h> is +included before genht's headers, it breaks. +

+Some more tracing showed it was because glib over-#defines the keyword +inline in a public header that gets included from glib.h. It's all wrapped +in a complicated tree of #ifdefs, so it behaves differently depending on +the --std setting. +

+The morale of the story is... Well, I have multiple conclusions. +

    +
  • glib is not a lib that tries to solve something, it is a proggamming +environment that tries to supersede C. + +
  • As such, it feels free to mess with the environment, redefine C +keywords as it sees fit, because once you use glib, why would you use +anything else? And once you use glib, you are programming in glib, not in +"plain C". + +
  • Grepping through the pcb-rnd code, I see that pcb-rnd does not try to +use glib as a programming environment, but needs only 2 and a half +features: hash, list and rarely dynamic strings. Any other glib call is +just a must that had to be done that way to get hashes and lists working. + +
  • genht is 510 sloc. I have a generic list implementation (which, by the +way, is more efficient than glib's) It costs 256 sloc. So having +type-independent hashes and lists in C89 costs less than 800 lines of code +if you pick the right libs. Glib's include/ alone is over 24000 sloc! +And in return glib breaks inline... +
+ +

+In a nutshell this is why I don't believe in glib-like solve-all megalibs. I +don't say size alone determines this, but size is a good indication of +potential problems. +

+If I need hash and lists and the offer is longer than 5k sloc, I know it +will bring a lot of unneeded bloat that likely to break things. + + + Index: tags/1.2.7/doc/devlog/20160101_cschem.html =================================================================== --- tags/1.2.7/doc/devlog/20160101_cschem.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160101_cschem.html (revision 13657) @@ -0,0 +1,69 @@ + + +

pcb-rnd devlog

+ +

cschem

+

by Igor2

+ +Cschem is a project I plan to start within the next few years. It's goals +and some design concepts are similar to gschem's and geda's, while it +also breaks some traditions in order to fix shortcomings in the design of geda. It's +named after gschem, not after geda, to emphasize that the editor needs to +be connected more to the rest of the system (see details later). +

+Some concepts cschem will try to follow (marking with * where there's major +difference to geda): +

    +
  • 1. design +
      +
    • 1.1. modularity, aka. toolkit approach +
    • 1.2. flexibility (trough attributes) +
    • 1.3. one schematics file is one sheet +
    • 1.4. multi page projects (hierarchic, flat) +
    • 1.5. data is in structured text files (no builtin sql support in core) +
    • 1.6. * the concept of a "project"; it's optional, tools can work on a set of schematics files _or_ on a complete project +
    • 1.7. * nets and components are uniquely identifiable using the same identifiers by all projects +
    • 1.8. * no excess "smartness" in the GUI editor: no slotting, no pin numbering, no auto renumbering, etc; these all should be done in the netlist layer and results fed back to the editor +
    • 1.9. * direct, bidirectional communication between the editor (GUI) and the netlist layer without any integration of the two, through simple and clean API, keeping both parts replaceable; attributes cschem got back from the netlister are "volatile": not saved, do not override attributes provided by the user +
    • 1.10. * less format-specific tricks built into the GUI code, more generic approaches (e.g. a search is a search, not a search-for-text-attribute and results on the result lists are any object of the design) +
    • 1.11. * slotting, pin mapping, device mapping are in backends +
    • 1.12. * back annotation should not be any harder than forward annotation +
    • 1.13. * since a lot of info is invented in backends, not in the GUI (e.g. pin numbers, when slotting), the GUI needs to be able to switch between "views": what (combination of) backend(s) to get these info from; Note: this would also provide an interactive DRC on the GUI with the DRC still implemented in the netlister! +
    • 1.14. * the scriptable plugin system is based on GPMI from the start to guarantee the tool is not tied to any one specific scripting engine or scripting language +
    +
  • 2. implementation +
      +
    • 2.1. a core library that does common things like figuring what objects are connected with net lines +
    • 2.2. the simple GUI editor should provide the frame; exotic functions should come from user plugins +
    • 2.3. a simple netlister that provides only generic (* absolutely no backend specific) queries; actual backends are implemented as plugins +
    • 2.4. * the core library and the netlister and the GUI core are all implemented in plain C: +
        +
      • 2.4.1. * no dependency on any specific scripting engine or scripting language; no core functionality implemented in anything else but C +
      • 2.4.2. * no dependency on big "solves-everything" libraries (e.g. no glib or cairo dependency) +
      • 2.4.3. * the actual GUI is behind the plugin system (like PCB's HIDs) +
      • 2.4.4. * the first gui, in accordance with the no big libraries, will not be gtk or qt but sdl2 based; this would guarantee to have a front end that doesn't need to be rewritten every 5 years just for the sake of the rewrite +
      • 2.4.5. * scconfig instead of autotools: smaller, easier to maintain, works better outside of the gnu-win32 world +
      +
    +
  • 3. project management +
      +
    • 3.1. automatic tests wherever possible, as early as possible +
    • 3.2. * VCS: simple, centralized svn with straight linear development, actively trying to avoid branching +
    • 3.3. * near-zero-administration releases with svn commits +
    • 3.4. * users should be able to submit bug reports anonymously, without having to register, without having to run javascript, java applet, flash, etc. +
    +
+ + +

+There are a lot of open questions: +

    +
  • q1. how buses should work +
  • q2. how slotting should work (but at least we can have alternatives here) +
  • q3. how hierarchical design should work +
  • q4. * how the GUI should display large amount of attributes without making the whole page an unreadable mess +
  • q5. flat vs. non-flat netlists - if turns out it's not just an implementation detail in a netlister backend +
  • q6. * whether project file format is a custom format or just a top sch page referencing other sch pages - pcb-rnd is leading here, there is an optional project file format already defined, so this is more or less decided +
  • q7. attribute conventions +
+ Index: tags/1.2.7/doc/devlog/20160126.html =================================================================== --- tags/1.2.7/doc/devlog/20160126.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160126.html (revision 13657) @@ -0,0 +1,60 @@ + + +

pcb-rnd devlog

+ +

Burried/blind via poll

+

by Igor2

+ +

Results

+ +I received 10 full answers to the poll - thanks everyone who +answered. This is a small sample, but this is the best I could get +(I can't reach more pcb users). +

+Raw results are available in html, tsv and +csv format. + +

My interpretation

+ +(User obviously means "those users who answered the poll") + +
    +
  • 1. only half of the users would consider even trying pcb-rnd for blind/burried vias +
  • 2. there was only one user who'd consider switching to pcb-rnd for blind-burried vias - this feature doesn't seem to be valuable enough to attract users (details below) +
  • 3. about half of the users need blind/burried via; when they do, they don't use pcb +
  • 4. 9 out of 10 users runs PCB on Linux +
+ +

My conclusions

+Because of 1. and 2., pcb-rnd doesn't seem to need blind/burried vias. The +purpose of question 7 was to find out whether users value this feature high +enough to actually consider investing time/effort in return, compared to +question 6. This pair of questions was designed to avoid noise that comes +from the fact that we, on the list tend to express our opinions in vast +crowds while only a few invest more time than talking and do actual work. +According to the result of line 7, my conclusion is that it's absolutely +not blind/burried vias that potential pcb-rnd users need. Thus +my decision is that I won't spend time on this feature in the near future. +

+The situation for pcb might be different, tho. I worded the first 4 questions +to find out how strong the need is among the users of mainline pcb and whether +they are devoted to pcb or choose the tool according to the design requirements. +There seems to be a correlation between having to use blind/burried vias +and using other layout tools. Or in other words: those who are happy with pcb +usually don't need or want blind/burried vias anyway and those who do have +already switched to another tool. +

+This suggests mainline pcb could benefit from burried/blind vias. However, +the demand is much lower than "every new design needs this" or "no new +user would consider pcb because of this missing feature". +

+Linux: it seems pcb power users mostly use Linux. I am not sure if it's +because PCB works well on Linux and is a bit harder to compile on +anything else - or the other way around (Linux users are more attracted +to PCB). + + + + + + Index: tags/1.2.7/doc/devlog/20160313_unglib.html =================================================================== --- tags/1.2.7/doc/devlog/20160313_unglib.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160313_unglib.html (revision 13657) @@ -0,0 +1,50 @@ + + +

pcb-rnd devlog

+ +

unglib: glib removal

+

by Igor2

+ +

glib problems

+ +As mentioned in a previous post, glib is +sometimes dangerous. Even if it was not, it's still huge and contradicts +the UNIX philosophy: Do One Thing and Do It Well. Glib tries to do a lot +of things. I do not doubt it is trying to do each of these things well, but as +a combination it's pretty much impossible to Keep It Simple, Stupid. +While glib is modular in design, from the viewpoint of an application it is +not modular: it's highly unlikely that the application can replace a part +of glib while keeping the rest. +

+The source of these problems is that glib is a "megalib" that tries to solve +a host of problems as a package. + +

The solution

+ +The solution is to replace the megalib with +a set of independent minilibs. Each minilib: +
    +
  • tries to do one thing - e.g. linked lists, without coupling it with a custom memory allocator +
  • is simple - the API is so small that it's easy to learn it in minutes +
  • is small - so that if anything breaks it's very easy to find and fix the bug (when did you last debug internals of glib?) +
  • is replaceable - since they are independent, if one doesn't work up to expectations, it's real easy to replace it without affecting any other part; e.g. replacing linked lists without replacing hash tables +
+

+The minilibs are imported as svn externals in trunk/src_3rd. They are small +enough so that they can be distributed together with pcb sources. + +

Current state

+ +The "unglib" patch is mostly done. All references of glib are removed +from the core and the lesstif hid. There are a three components that +still depend on glib, but they each can be disabled: +
    +
  • the GTK HID: because gtk is already coupled with glib, it doesn't make much sense to remove glib from the gtk HID code +
  • the toporouter plugin: the code is huge and will be potentially deprecated anyway (lack of developer resources/user interest) +
  • the puller: glib should be removed from the puller long term but the code is big and there's no much user need for it in pcb-rnd +
+

+This means pcb-rnd can be compiled with lesstif (or a compatible motif) +on a UNIX box without depending on glib. Together with the earlier effort +that removed autotools, it means a UNIX box without any "GNU infection" +should be able to compile and run pcb-rnd. Index: tags/1.2.7/doc/devlog/20160314_valgrind_flex.html =================================================================== --- tags/1.2.7/doc/devlog/20160314_valgrind_flex.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160314_valgrind_flex.html (revision 13657) @@ -0,0 +1,80 @@ + + +

pcb-rnd devlog

+ +

"valgrinding" flex/bison parsers

+

by Igor2

+ +In a flex/bison parser it's quiet common that strings are allocated +in flex, passed on to bison and then either free'd there or saved in +the output data. Since both free and save happens a lot, it's not an +easy mechanical review of the .y file to find the reason for leaks. Especially +if the code has to store some strings in temporary storage until a later +stage of the parsing. +

+A typical valgrind log for such a leak looks like this: +

+==20520== 20 bytes in 1 blocks are still reachable in loss record 3 of 6
+==20520==    at 0x402B0D5: calloc (vg_replace_malloc.c:623)
+==20520==    by 0x80E6EF0: yylex (parse_l.l:177)
+==20520==    by 0x80E0D6C: yyparse (parse_y.tab.c:1696)
+==20520==    by 0x80E85ED: Parse (parse_l.l:292)
+==20520==    by 0x80E876B: ParsePCB (parse_l.l:347)
+==20520==    by 0x8078591: real_load_pcb (file.c:390)
+==20520==    by 0x80787E9: LoadPCB (file.c:459)
+==20520==    by 0x8097719: main (main.c:1781)
+
+ +The code at parse_l.l:177 is just a calloc() and some string +operation: this is where the string is created. The STRING token is +referenced about 58 times in the grammar. After reading through the +whole file 4..5 times, I still didn't see any obvious place for the leak. +

+The leak was also a rare one: happened for one string per file. This suggested +it was in the header - unless there's an one-instance object somewhere in the +.pcb or it's a cache where the same pointer is free()'d and overwritten for +multiple occurrences and simply no one free()'s the last. +

+Assuming it's a header, a cheap ways to find which header field leaked: +

    +
  • remove the header lines one by one and see if the leak is still there - won't work if a missing header changes how the whole code runs +
  • change the size of each header, one by one, and see which action changes leak size - a lot of iterations, and valgrinding is slow +
+

+At this point I figured that I'd depend on the reported size of the leak +with my tests. I didn't want to do multiple runs and didn't want to risk +the whole parser to run differently so I didn't want to modify the input. Instead +I figured there's a simple, yet generic way to track these sort of leaks. +

+I estimated no string in the file is longer than 1000 characters. Right above +the calloc() in the lexer I introduced a new static integer variable starting +at 1000, increased before each allocation. This counter is sort of an ID of +each allocation. Then I modified the calloc() to ignore the originally calculated +string length and use this ID for allocation size. I also printed the ID-string +pairs. The original code looked like this (simplified): +

+	/* ... predict string size ... */
+	yylval.str = calloc(predicted_size, 1);
+	/* ... build the string here ... */
+	return STRING;
+
+ +The resulting code looked like this (simplified): +
+	/* ... predict string size ... */
+	static int alloc_id = 1000;
+	alloc_id++;
+	yylval.str = calloc(alloc_id, 1);
+	/* ... build the string here ... */
+	fprintf(stderr, "STRING: %d '%s'\n", alloc_id, yylval.str);
+	return STRING;
+
+I saved the list printed on stderr and checked valgrind's log to find +the two strings in question were ID 1002 and ID 1007, both looked +something like this: +
+1,3,4,c:2,5,6,s:7:8
+
+The only thing that looks like this is the layer group description ("Groups()"). +From this point it was trivial to find the bug in the grammar. + Index: tags/1.2.7/doc/devlog/20160409/header =================================================================== --- tags/1.2.7/doc/devlog/20160409/header (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/header (revision 13657) @@ -0,0 +1,7 @@ +1. Do you use the lesstif HID? +2. If there were different menu resources files distributed with PCB, would you try them? +3. Do you customize your menu resource file? +4. If you do not customize your menu resource file, it's because +5. Do you miss multi-key sequences from the GTK hid? +6. If the GTK hid supported multi-key sequences, would that change any of your previous answers? +7. Vendor (drill) mapping also uses a resource file. Index: tags/1.2.7/doc/devlog/20160409/header.csv =================================================================== --- tags/1.2.7/doc/devlog/20160409/header.csv (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/header.csv (revision 13657) @@ -0,0 +1 @@ +1. Do you use the lesstif HID?,2. If there were different menu resources files distributed with PCB, would you try them?,3. Do you customize your menu resource file?,4. If you do not customize your menu resource file, it's because,5. Do you miss multi-key sequences from the GTK hid?,6. If the GTK hid supported multi-key sequences, would that change any of your previous answers?,7. Vendor (drill) mapping also uses a resource file., Index: tags/1.2.7/doc/devlog/20160409/legend.txt =================================================================== --- tags/1.2.7/doc/devlog/20160409/legend.txt (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/legend.txt (revision 13657) @@ -0,0 +1,60 @@ +1. Do you use the lesstif HID? (select one) +a. yes, exclusively +b. yes, often +c. sometimes, rarely +d. never + + +2. If there were different menu resources files distributed with PCB, +would you try them? (select one) +a. yes, I'd give each variant a try before deciding which one to use +b. no, I'm fine with the default +c. I don't know what a menu resource file is + + +3. Do you customize your menu resource file? (select one) +a. yes, always (e.g. I have an own variant I use with all installation of +PCB) +b. yes, sometimes, rarely (e.g. I once had to do something repeatedly and +added a key binding for that) +c. never, I know where I'd perform the changes if I ever needed +them but defaults are good enough for now +d. never, I don't know what a menu resource file is + + +4. If you do not customize your menu resource file, it's because (select +zero or more): +a. I don't need to +b. the file is too long +c. too many keys are taken, it's hard to find a free one +d. I don't like the format of the file +e. I don't like the idea of editing text config files, I want a GUI for +this +f. I don't want to diverge from the default settings (e.g. because of +potential hassle at a later upgrade) + + +5. Do you miss multi-key sequences from the GTK hid? (select one) +a. yes, I'd prefer to use them over modifiers (ctrl, alt, shift) +b. yes, I'd use them together with the modifiers +c. maybe I'd use some +d. no, I prefer modifiers +e. I hate the idea so much that I'd even disable it compile time if that +was possible +f. N/A, don't know + + +6. If the GTK hid supported multi-key sequences, would that change any of +your previous answers? (fill in zero or more with a letter) +a. my new choice for 2. would be: +b. my new choice for 3. would be: + +7. slightly off-topic: vendor (drill) mapping also uses a resource file. +Do you use this feature? (select one) +a. yes, often, many of my boards rely on vendor mapping and I maintain +my own resource files per vendor +b. yes, sometimes, rarely (e.g. I needed it once...) +c. no, I know how to use it but never needed it +d. no, I know the feature exists and I know where to look it up but I +don't really know what exactly it can do or why I should bother +e. no, I never heard about this feature Index: tags/1.2.7/doc/devlog/20160409/pie_col_1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_1.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_1.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_1.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/pie_col_2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_2.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_2.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_2.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/pie_col_3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_3.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_3.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_3.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/pie_col_4.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_4.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_4.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_4.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_4.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/pie_col_5.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_5.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_5.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_5.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_5.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/pie_col_7.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20160409/pie_col_7.png =================================================================== --- tags/1.2.7/doc/devlog/20160409/pie_col_7.png (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/pie_col_7.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20160409/pie_col_7.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20160409/poll.csv =================================================================== --- tags/1.2.7/doc/devlog/20160409/poll.csv (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/poll.csv (revision 13657) @@ -0,0 +1,9 @@ +a,a,a,-,-,-,c +d,a,c,f,a,-,d +b,a,b,-,c,-,c +d,c,d,a+f,c,-,e +d,b,c,a+f,b,-,b +d,a,a,a,d,-,c +-,a,c,-,a,-,- +c,a,b,f,a,-,c +c,a,c,-,a,-,- Index: tags/1.2.7/doc/devlog/20160409/poll.html =================================================================== --- tags/1.2.7/doc/devlog/20160409/poll.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/poll.html (revision 13657) @@ -0,0 +1,98 @@ + + + +
1. Do you use the lesstif HID? +2. If there were different menu resources files distributed with PCB, would you try them? +3. Do you customize your menu resource file? +4. If you do not customize your menu resource file, it's because +5. Do you miss multi-key sequences from the GTK hid? +6. If the GTK hid supported multi-key sequences, would that change any of your previous answers? +7. Vendor (drill) mapping also uses a resource file. +
aaa---c +
dacfa-d +
bab-c-c +
dcda+fc-e +
dbca+fb-b +
daaad-c +
-ac-a-- +
cabfa-c +
cac-a-- +
+ + + + +  + +
+

+

Legend

+
+1. Do you use the lesstif HID? (select one)
+a. yes, exclusively
+b. yes, often
+c. sometimes, rarely
+d. never
+
+
+2. If there were different menu resources files distributed with PCB, 
+would you try them? (select one)
+a. yes, I'd give each variant a try before deciding which one to use
+b. no, I'm fine with the default
+c. I don't know what a menu resource file is
+
+
+3. Do you customize your menu resource file? (select one)
+a. yes, always (e.g. I have an own variant I use with all installation of 
+PCB)
+b. yes, sometimes, rarely (e.g. I once had to do something repeatedly and 
+added a key binding for that)
+c. never, I know where I'd perform the changes if I ever needed 
+them but defaults are good enough for now
+d. never, I don't know what a menu resource file is
+
+
+4. If you do not customize your menu resource file, it's because (select 
+zero or more):
+a. I don't need to
+b. the file is too long
+c. too many keys are taken, it's hard to find a free one
+d. I don't like the format of the file
+e. I don't like the idea of editing text config files, I want a GUI for 
+this
+f. I don't want to diverge from the default settings (e.g. because of 
+potential hassle at a later upgrade)
+
+
+5. Do you miss multi-key sequences from the GTK hid? (select one)
+a. yes, I'd prefer to use them over modifiers (ctrl, alt, shift)
+b. yes, I'd use them together with the modifiers
+c. maybe I'd use some
+d. no, I prefer modifiers
+e. I hate the idea so much that I'd even disable it compile time if that 
+was possible
+f. N/A, don't know
+
+
+6. If the GTK hid supported multi-key sequences, would that change any of 
+your previous answers? (fill in zero or more with a letter)
+a. my new choice for 2. would be:
+b. my new choice for 3. would be:
+
+7. slightly off-topic: vendor (drill) mapping also uses a resource file. 
+Do you use this feature? (select one)
+a. yes, often, many of my boards rely on vendor mapping and I maintain 
+my own resource files per vendor
+b. yes, sometimes, rarely (e.g. I needed it once...)
+c. no, I know how to use it but never needed it
+d. no, I know the feature exists and I know where to look it up but I 
+don't really know what exactly it can do or why I should bother
+e. no, I never heard about this feature
+
+

Downloads

+
    +
  • csv data | csv header +
  • tsv data (raw, no header) +
  • legend +
      + Index: tags/1.2.7/doc/devlog/20160409/poll.tsv =================================================================== --- tags/1.2.7/doc/devlog/20160409/poll.tsv (nonexistent) +++ tags/1.2.7/doc/devlog/20160409/poll.tsv (revision 13657) @@ -0,0 +1,9 @@ +a a a - - - c +d a c f a - d +b a b - c - c +d c d a+f c - e +d b c a+f b - b +d a a a d - c +- a c - a - - +c a b f a - c +c a c - a - - Index: tags/1.2.7/doc/devlog/20160409.html =================================================================== --- tags/1.2.7/doc/devlog/20160409.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160409.html (revision 13657) @@ -0,0 +1,49 @@ + + +

      pcb-rnd devlog

      + +

      Keyboard via poll

      +

      by Igor2

      + +

      Results

      + +I received 9 partial answers to the poll - thanks everyone who +answered. This is a small sample, but this is the best I could get +(I can't reach more pcb users). +

      +Raw results are available in html, tsv and +csv format. + +

      My interpretation

      + +(User obviously means "those users who answered the poll") + +
        +
      • 1. very few users use the lesstif hid, still user count is more than 1 +
      • 2. users are open to try alternative menu/hotkey layouts... +
      • 3. ... and only a few users change the default layout +
      • 4. ... because they are happy with the defaults and/or don't want to maintain the diffs on upgrades +
      • 5. there is a strong demand for multikey in the GTK HID +
      • 7. use of vendor (drill) mapping is rare +
      + +

      My conclusions

      +pcb-rnd: the GTK HID needs multi-key support. +

      +Community: although users express their needs, they do not contribute +even in smallish, non-programming tasks like designing the hotkey layout. +This is probably in-line with the answers for 4: they don't really customize +things, they want to use the software as is. +

      +Conclusion: it is worth shipping multiple menu/keyboard layouts as long as +they are all maintained in the central repo (questions 2, 3 and 4). It is +pointless to invest in tools that make customization easier or to prepare +for collecting user-customized menu files, as users won't invest any time in +this. + + + + + + + Index: tags/1.2.7/doc/devlog/20160716_sprint.html =================================================================== --- tags/1.2.7/doc/devlog/20160716_sprint.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160716_sprint.html (revision 13657) @@ -0,0 +1,82 @@ + + +

      pcb-rnd devlog

      + +

      Testing guide for the test sprint

      +

      by Igor2

      + +Please start with procedure I and proceed to procedure II then to procedure III. +You can postpone or stop any time, even partial results are useful. +

      +The most important procedures are I. and II., which together are estimated +to take something between 40 and 90 minutes. +

      +No installation, no root privileges required. No interference expected with +your pcb mainline installation. What you'll need is about the same you would +need for compiling mainline or a random application: +

        +
      • an svn client (e.g. apt-get install subversion) +
      • a C compiler (e.g. apt-get install gcc - anything that supports C99 should work) +
      • the normal development libs (e.g. libc) +
      • extra libs depending on your desired setup (e.g. libgtk2-0-dev) +
      • make +
      + +

      I. Setup [10..30 minutes]

      +
        +
      • Objective: get a running pcb-rnd. +
      • steps: +
          +
        • 1. check out the code in a new directory: svn checkout svn://repo.hu/pcb-rnd/trunk +
        • 2. configure: cd trunk; ./configure +
        • 3. check the summary the last step produced; if you don't like it or anything is suspicious, consult Igor2 on IRC +
        • 4. compile: cd trunk; make +
        • 5. check if the compilation terminated with error (->Igor2 on IRC) +
        • 6. dry run: cd trunk/src; ./pcb-rnd +
        • 7. check if it generally runs as expected (note: there's no opengl, the menu layout and some default settings are slightly different) +
        • 8. please report even if everything worked: it's for the record/statistics; please include, in your report: +
            +
          • a. your system: uname -a +
          • b. whether you used the gtk HID or the lesstif HID or both +
          +
        +
      + +

      II. Test drive [30..60 minutes]

      + +
        +
      • Objective: find random bugs and make suggestions via a simulated production test drive. +
      • steps: +
          +
        • 1. take on of your existing .pcb (preferably one that you can share in case of a bugreport is needed) +
        • 2. copy the .pcb to trunk/src as foo.pcb +
        • 3. run cd trunk/src; ./pcb-rnd foo.pcb +
        • 4. pretend carrying out a real modification; e.g. replace one of the ICs with a footprint of the same pin count but different dimensions (e.g. so8 -> ssop8 or sot23->to220). Pretend you really want to do this modification and pretend that the board will go in production. Do your usual routine (e.g. check gerbers). +
        • 5. if you see anything strange, find bugs, have suggestions: +
            +
          • a. consult Igor2 on IRC +
          • b. if there are files to be "attached" or your observation/question can only be stated in a medium sized novel, please send an email to pcb-rnd (at) igor2.repo.hu (and then we can still discuss it on IRC) +
          • c. it is sometimes worth checking the behavior of a recent mainline pcb; there are bugs and oddities present in both current mainline and pcb-rnd (because of the common ancestor) +
          +
        +
      + +

      III. Systematic testing [60..90]

      +
        +
      • Objective: systematic testing of specific features that are affected + by recent code rewrite/development. +
      • steps: +
          +
        • 1. contact Igor2 on IRC to get a chunk of the tests +
        • 2. understand the subsystem in question (from user perspective) +
        • 3. use your fantasy to invent test methods to see whether the + subsystem works in common or normal use cases +
        • 4. use your fantasy to invent test methods to see whether the + subsystem works in corner cases +
        • 5. report anything that seems like a bug or undesired behavior or regression +
        • 6. please do report if there's no bug and the given subsystem + worked as expected; positive results are just as important as negative ones +
        • 7. start over from step III/1. +
        + + Index: tags/1.2.7/doc/devlog/20160802.html =================================================================== --- tags/1.2.7/doc/devlog/20160802.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160802.html (revision 13657) @@ -0,0 +1,26 @@ + + +

        pcb-rnd devlog

        + +

        Languages and libs

        +

        by Igor2

        +

        +Reflecting to (but not joining) the annual geda-user language/libs debate, +the policy of pcb-rnd (and later cschem) on this: +

          +
        • the core part of the code is in C - not in C++, C#, cobol, ada, haskell, etc. +
        • external dependencies are minimized, especially core shouldn't depend on too many external libs and tools (e.g. core shouldn't depend on glib) +
        • core doesn't know anything about [turing complete] scripting languages, user scripting is provided by a plugin +
        • the scripting plugin does not attempt to restrict the user to My Favorite Language - it rather supports 10+ different languages, from ruby through awk through python to lua; it even supports an older version of guile; all languages are options. +
        +The above set of rules is crafted so that compiling core functionality is easy +and excess external libs (gtk, glib) are needed only for optional features +(such as the gtk hid in pcb-rnd). However, it's equally important not to +restrict users in optional extras that may require more dependencies. This is +solved by minimizing core and moving functionality behind APIs in a plugin +system. +

        +This policy is very unlikely to change in the future - if you believe +the core should be rewritten in your favorite language, please fork the +project or start a new one. + Index: tags/1.2.7/doc/devlog/20160808_model.html =================================================================== --- tags/1.2.7/doc/devlog/20160808_model.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160808_model.html (revision 13657) @@ -0,0 +1,102 @@ + + +

        pcb-rnd devlog

        + +

        How to represent the world in pcb-rnd

        +

        by Igor2

        + +

        Proper implementation

        + +<daydreaming> +

        +In a proper model there's no element/footprint. There are a few simple +primitives and there are groups, like the ones in svg: groups contain +metadata, primitives and groups. +

        +An element is just a group. The whole design may contain groups of groups +of groups. A stereo amplifier may be a group for a PSU and two instances +of a single-channel amp group that match square-unit to square-unit. +

        +What makes up an element now is a refdes, its pins/pads we can identify +(for the netlist-related things) and the feature that you can drag the +whole thing as one. A group could do all these as well: refdes is just +metadata, silk lines are just primitives, pins/pads are just small groups +of primitives and metadata. +

        +There could be "group types" and type-specific code handling them. In such +a setup you probably don't need to have a text object: just a group that +consists of mostly lines (or polygons) and some metadata (the string +version of the text); the group type would assigns the text-handling code +with to the group. So for the rest of the code, text is not a special +thing, not a bounding box, but just a set of primitives. When you edit it, +you can edit it either line-by-line or as text with the assigned code. +

        +This would allow us to have a very small amount of primitives: line, arc, +poly, hole (without a ring - a via is just a group of a few primitives). +Each primitive would have a layer-span field; this would solve the +blind/buried via question for good. (In theory line and arc could be one +thing, spline oslt, but I don't think performance penalty is worth that.) +

        +However, this means a total rewrite as almost every non-trivial piece of +the code depends on the object model, from find/search/drc to the whole +polygon code, just to name two huge ones. The file format thing is the +smallest of this all. The only major parts I think we could keep are the +GUI and the new conf system. At the current rate of development this would +take more than a year to have a mostly working version and probably yet +another year to get everything tested out and reach current level of +service again. +

        +I am not against such a rewrite, but it would really need a very strong +user/tester backing and maybe more developers than the current amount. +

        +Also, Imagine we'd have a pcb program you couldn't trust on +anything: e.g. losing your data, generating broken gerber, etc. for a very +long time... +

        +So I generally agree that we should do this, but for practical reasons I +am a bit skeptic whether this would work out in the current situation. +It'd kill any cschem plans for years, and because of the long development +cycle it would most probably kill pcb-rnd too. +

        +</daydreaming> + +

        Improper implementation

        + +However, I see an alternative that is not as good as the real thing, but +might be good enough that users don't see much difference. It's +possible to implement it step by step, without long years of "nothing +works as used to" phases. The alternative is: +

        +

          +
        • 1. Add io_lihata, first as a second native file format option, but long +term as the primary file format; it's because we can't really extend the +code without breaking compatibility with mainline on the .pcb format. In +other words, we either _pretend_ we are compatible, but using any new +feature would break compatibility (current state) or we admit that new +features are implemented only in the lihata syntax and when you save to +.pcb it's like saving png from gimp, losing some extra layer info. This +step will happen either way, for other reasons. + +
        • 2. rearrange some internals; the core is currently split per operation +(e.g. there's create.c for creating all sort of objects and remove.c +for removing them). The new setup should be per object type (e.g. arc.c +that knows how to create or remove arcs). + +
        • 3. Once lihata is in place, we can extend/rewrite some parts. An option +is to rewrite footprint support to allow them to be sort of a small pcb +design. So objects on arbitrary layers, footprint-in-footprint, etc. + +
        • 4. When 3. is done, we could extend element handling so that pcb-rnd knows +which element is there for why. So you could have some real elements, with +refdes, part of the netlist, etc, but you could also do a panelization as +a matrix of full pcb designs place like if they were elements. +
        +

        +This 3.,4. would not be the same as building up everything from generic +atoms, but would be close to it and would be much simpler to implement +(still a big one, tho). I believe in practice, for end users, it would +probably be 99% the same as the proper solution. +

        +I believe 3.,4. would be more or less the pcb-rnd equivalent of gschem's +implementation of schematics and symbols with about the same level of +generalism. Not perfect, but maybe good enough. Index: tags/1.2.7/doc/devlog/20160823_lhtpers.html =================================================================== --- tags/1.2.7/doc/devlog/20160823_lhtpers.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160823_lhtpers.html (revision 13657) @@ -0,0 +1,210 @@ + + +

        pcb-rnd devlog

        + +

        File format vs. VCS vs. script and manual editing

        +

        by Igor2

        + +

        The problem

        + +The file a CAD program loads and saves is likely to end up in a Version +Control System (VCS) sooner or later. To make VCS more meaningful, the +changes to the file need to be minimal and relevant. For example in a +load-save round trip (i.e. load the file in the CAD and save it in another +file without any modification) the diff should be empty. If the user adds a new +object, the diff should contain only lines added for the new object. (And maybe +a few lines of changes in an index, if there's an index, but I believe it's +better if there's no index.) Likewise, if an object is deleted, it is expected +to result a few lines removed, preferably at a single location. + +

        +Terminology used in this document: +

          +
        • file is the data file, represented in a structured text format; + for the whole document except for the last chapter, any format may work: + xml, json, ini, lihata, etc. +
        • node a data node; may be: +
            +
          • a leaf node with payload: an actual data item (like a number) +
          • a hash that contains an unordered set of other named nodes +
          • a list is an ordered list of named or unnamed nodes +
          +
        +

        +The file is a tree; even an ini file is a tree with 1 or 2 levels (bottom +level is a hash of text nodes, top level, groups, represent another hash). An +xml is a list of lists with text nodes and non-text-node attributes +representing a hash. + +

        Problem #0: order

        +To achieve the above goals, both gschem and pcb and pcb-rnd are prudent: +objects are ordered in memory. This is necessary because in an unordered +list or hash if the number of objects changes (objects added or removed) +the saving order may shuffle, causing a lot of unnecessary changes. +

        +This problem is already solved. + +

        Problem #1: canonical form

        +Our file formats are plain text. While there are certain constructs that have +strict format, e.g. a string in quotes can be described only one way without +changing the content of the string, other parts have alternatives: +
          +
        • white spaces and other field separators +
        • numerical formats: is 8 the same as 08 or 8.0? +
        • pcb flag formats, old/new style: the same object can be described + using different syntax constructions, sometimes resulting the same + object +
        +

        +This problem is seemingly solved by using a canonical form: even if the +loader may accept alternatives, the save code always generates the same formatted +output, down to the last whitespace indentation. + +

        Problem #2: hand editing, external scripts

        +However, the canonical format is not always the most convenient for the user. +Sometimes different indentation, maybe even locally, may improve readability. +Unfortunately a CAD round-trip brings back the file to canonical format, removing +any user formatting. Or in other words, the user needs to learn the syntax +of the file format and how the canonical format looks like, else user +changes to a file may cause VCS noise later. +

        +Even worse, 3rd party scripts need to learn the canonical format too, for the +same reason. + + +

        The solution

        +One solution is to merge the canonical format and the syntax, so the resulting +specification is so strict that there are no alternatives but everything can +be written using only a single, well described format. This solves problem +#1 and #2, but creates problem #3: a text file format as rigid as a binary +format would be. While it could be still parsed by text tools easily, it +would be much harder to emit properly using the same tools or even harder to +edit manually, with a text editor. In this sense it may start losing its +most important text-file-property: free form, to some extent. +

        +An alternative is that the CAD program doesn't save canonical format over +an existing file but tries to accommodate to the format the file already features. +This solves problem #0, #1, #2 and #3, allowing the user (or 3rd party scripts) +to use whatever formatting they prefer, with clean round trips. + +

        How to implement it (in theory)

        +A few unusual features are required: +
          +
        • F1: the parser needs to be aware of otherwise unimportant + characters (e.g. whitespace in indentation) +
        • F2: if (payload) data is to be converted to a native format by + the program, the original text representation needs to be saved; + e.g. the input file contains 4.99999999, the program loads it to + a float and later saved back, it may end up as 4.999997836; + instead if the data did not change, the original text shall be + saved back; this also solves the 005 vs 5 vs 5.0 problem +
        • F3: new data should be inserted, obsolete data should be removed + without reordering stationary data +
        + +

        The obvious approach

        +An obvious approach would be to smarten the parser and store delimiters +(e.g. whitespace) and the original text version for each data node, along with +the order of nodes in the original file. + +

        The less obvious approach

        +A second approach is to ignore these details on load and keep on storing data +in native binary format in memory. On save, start parsing the original file +(or a snapshot of it taken load-time), and: +
          +
        • any non-data-payload character should be copied the the output; + this includes whitespace, delimiters, comments, syntax sugar; + this solves F1 +
        • if a node did not change, the parser copies it byte-to-byte to + the output (solves F2 partially - no format change if data is + unchanged in memory); +
        • value change check: while parsing, convert the original value to + native format again and compare, which solves F2: the same + string->native conversion should yield the same native result; + if our in-memory representation differs, it has changed and the + new value should be copied to the output instead of the old value; + the format of the new value doesn't matter, can be canonical, since + the diff is already caused by the fact that the value has changed. +
        • if the language supports ordered lists: before emitting list items, + the input list must be read through (pre-read) and the in-memory and + just-parse lists need to be compared to detect changes in order; + existing list items are copied as described above; list items + deleted in-memory are ignored; list items added in-memory are + written out (solves F3) +
        • if the language supports unordered hashes: check each key parsed; + if it exists in-memory, copy/write it normally; if it doesn't, + delete it; add new hash items (the ones present in-memory but + not seen when the parser reaches the end of the hash; solves F3) +
        +

        +This may sound more expensive than the first approach, because the parser needs +to run again on save. However, the costs of the previous approach are +high too: +

          +
        • essentially the whole file needs to be stored in-memory + (for whitespace), but not in one bug chunk but in many + little chunks among with the data nodes (which leads to + allocation overhead); the original values need to be stored in + text too, to solve the numeric problems +
        • either the same string->native conversion needs to be done using + stored text values; or the code needs to keep track of which node + changed using some data-changed bit +
        • the same list/hash merging needs to be done +
        +

        +If the syntax-sugar overhead of the file format is low, majority of all +bytes will be actual node data (need to be stored) and delimiters/indentation +(need to be stored). Then it might be cheaper to store it all in one bug chunk +and re-parse it (without building a DOM) than storing the same data in small +chunks. + + +

        An even less obvious approach

        +Take the previous method, but assume the application does not change the +order of objects on ordered lists and each object has some sort of unique +identifier (so two identical looking objects can't be on a list). +This makes list merging much simpler and doable in a single pass, keeping +a list item pointer with the in-memory list: +
          +
        • initialization: set the pointer to the first element of the list +
        • iteration: parse the first (next) item of the list +
        • check if it exists in-memory and is the first +
            +
          • if yes, copy from the original file, increase the pointer by + one element +
          • if not, check if it got deleted (not present on the list + in-memory) and skip it if so; pointer stays in place +
          • if not, check if it is on the in-memory list as a later entry; + if so, insert all preceding entries from the in-memory list, + increasing the pointer by one for each element written +
          +
        • repeat the iteration until there are no more items on the input list +
        • check if there are items remaining from the pointer, if so output + them (they will end up at the end of the list in the output file) +
        • finished: the output file's list now matches the in-memory list. +
        +

        +Empty lists may need special (but trivial) treatment. +

        +While copying an existing node, it is possible to "pick up" style +e.g. indentation. When a new item needs to be added, such picked up local +style info can be used to generate output that looks similar to other items +in its local environment. For example the first time a list or hash item +needs to be added is right after at least one item of the given hash or +list is already parsed, which means the style of an item is already know. + +

        How it is implemented in practice

        +Using the last approach from the above list, with an utility library for +lihata. The full list of requirements (on the application and the tree +structure): +
          +
        • the root element of the input file and the in-memory representation + must fully match +
        • list items must have names that are unique to the list, even across + item removal from the list within a session (so a newly added item + never has the same name as a past item parsed back from the file) +
        • the application must not change the order of elements on a list - + new elements may be inserted anywhere and old elements may be + removed from anywhere but the order of any two remaining old + elements must be preserved +
        Index: tags/1.2.7/doc/devlog/20160826_virtusers.html =================================================================== --- tags/1.2.7/doc/devlog/20160826_virtusers.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160826_virtusers.html (revision 13657) @@ -0,0 +1,66 @@ + + +

        pcb-rnd devlog

        + +

        Offer vs. pull (virtual users vs. active users)

        +Pcb-rnd has an pulled-by-users policy on deciding what features to implement. +Below I try to explain how we ended up using this policy. +

        by Igor2

        + +

        Past: offer, virtual users

        + +When I started pcb-rnd, although I published it, I didn't think anyone else +would use it. It was just about having mainline with different default +settings. +

        +Later on I added a few features, and pcb-rnd slowly became much more than +just different defaults. I felt other users may find the new features useful, +so I had put it on offer: advertised the repository. I thought users +would download and try the software. Judging from the feedback, they didn't. I +didn't mind, because I was working on features I needed, to get pcb-rnd do what +I wanted: I was my own target audience and anyone else trying pcb-rnd could +only be a side effect. Until when I ran out of features because it already +had everything I needed. +

        +The next step was to implement features for other users. Between summer +of 2015 and summer of 2016, I tried to be a bit more proactive: made +public polls to map what users needed and tried to focus implementing +those features. This did not bring too many users either. +

        +This was when I realized what was really happening: I was offering +features for virtual users, addressing my communication to the wide +audience. Noone really felt it was for him. Even if he was complaining about +a missing feature in pcb and a few days later I announced the fix in pcb-rnd, it +was not specifically for him, but for the Greater Good. +

        +Virtual users nearly never became real users. My conclusion was that there +was no point in implementing features for virtual users as noone ever would +use those features. + +

        Present: pull, active users

        +Mid summer 2016, I switched strategy. Instead of polling the crowd, I picked +a few users with known feature requests and asked them if they were willing to +test pcb-rnd if I implemented their feature. More than half of them said yes +and many of them got hooked up. They all became productive, active members +of the pcb-rnd community. +

        +Learning from this experience, the new strategy of pcb-rnd is as follows: +

          +
        • pull instead of offer: do not hope a new feature would attract users, + rather arrange active users who then pull the project with their + feature requests; +
        • do not invest too much time in anything that is not currently pulled + by actual, existing, active users; rather invest that time in fulfilling + the needs of already existing users +
        • reaching 100 users with an average of 0.1% activity will result in + 0 active users whereas reaching only 10 users with 30% activity + will result in 3 active users; thus a small active community around + pcb-rnd is more efficient than the much larger geda community; +
        • users really appreciate fast response on bugreports and feature requests. + Instead of trying to impress virtual users, rather keep already interested + users happy. +
        + + + + Index: tags/1.2.7/doc/devlog/20160921_gl.html =================================================================== --- tags/1.2.7/doc/devlog/20160921_gl.html (nonexistent) +++ tags/1.2.7/doc/devlog/20160921_gl.html (revision 13657) @@ -0,0 +1,10 @@ + + +

        pcb-rnd devlog

        + +

        what's missing for: opengl

        +

        by Igor2

        + +

        +(Updated in March 2017) +Nothing. Use a sufficiently recent version and use the gtk2_gl hid. Index: tags/1.2.7/doc/devlog/20161014_cleanup.html =================================================================== --- tags/1.2.7/doc/devlog/20161014_cleanup.html (nonexistent) +++ tags/1.2.7/doc/devlog/20161014_cleanup.html (revision 13657) @@ -0,0 +1,37 @@ + + +

        pcb-rnd devlog

        + +

        The way forward on cleanup

        +

        by Igor2

        +

        +This is a long term plan (these will happen slowly, step-by-step, gradually, in +the background, in parallel with the normal schedule of development: +

          +
        • phase 0: port the rest [almost done] +
            +
          • import the remaining plugins and exporters before the big cleanup because it's cheaper to port them now +
          +
        • phase 1: reorg +
            +
          • reorganize the code: from action-oriented (e.g. change.c, remove.c, mirror.c) into object-type-oriented code (e.g. obj_line.c, obj_arc.c) +
          • global*.h must be dissolved/removed +
          • macro.h should be dissolved/removed +
          • const.h should be reduced to 1/3 +
          +
        • phase 2: clean the namespace +
            +
          • pcb_ prefixes +
          • unify convention: underscores instead of CamelCase, prefer shorter names +
          • better connection between file name and function name prefixes (don't invent 3 different names for the same thing) +
          +
        • phase 3: split & pack +
            +
          • move out generic, non-pcb-specific code to "external libs" (e.g. polygon, heap, the conf system) +
          • determine layering of the new lib system (e.g. a generic unit, printf, etc. util lib on layer 0, then a lib about the basic object types on layer 1, then footprint libraries and other plugins on layer 2) +
          • compile one .a file per layer, link the final executable using those .a files +
          • make the libs installable, together with the headers +
          • fix gsch2pcb-rnd to use the new lib(s) +
          +
        + Index: tags/1.2.7/doc/devlog/20162601/header =================================================================== --- tags/1.2.7/doc/devlog/20162601/header (nonexistent) +++ tags/1.2.7/doc/devlog/20162601/header (revision 13657) @@ -0,0 +1,11 @@ +1. How many of your boards REQUIRE burried or blind vias? [percentage] +2. How many of your boards could BENEFIT burried or blind vias? [percentage] +3. When your board REQUIRED them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no] +4. When your board could BENEFIT using them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no] +5. Have you ever tried pcb-rnd? [yes/no] +6. Would you try pcb-rnd if it offered blind/burried vias? [yes/no] +7. Would you consider switching to pcb-rnd if it offered blind/burried vias? [yes/no] +8. Approximately how many boards have you done so far with pcb (pcb mainline/branches/forks included, using gschem/gnetlist not required)? "1 board done" means you had one or more physical copies of the board. [rough estimation, positive integer] +9. Approximately how many boards have you done with other packages? [rough estimation, positive integer] +10. What OS would you prefer to do your pcb layouts on (assuming your favorite layout tool is/would be available on it)? [one of: (GNU/)Linux, *BSD, OSX, windows, other; if you like more, select the one you would spend most time on!] + Index: tags/1.2.7/doc/devlog/20162601/header.csv =================================================================== --- tags/1.2.7/doc/devlog/20162601/header.csv (nonexistent) +++ tags/1.2.7/doc/devlog/20162601/header.csv (revision 13657) @@ -0,0 +1 @@ +1. How many of your boards REQUIRE burried or blind vias? [percentage],2. How many of your boards could BENEFIT burried or blind vias? [percentage],3. When your board REQUIRED them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no],4. When your board could BENEFIT using them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no],5. Have you ever tried pcb-rnd? [yes/no],6. Would you try pcb-rnd if it offered blind/burried vias? [yes/no],7. Would you consider switching to pcb-rnd if it offered blind/burried vias? [yes/no],8. Approximately how many boards have you done so far with pcb (pcb mainline/branches/forks included, using gschem/gnetlist not required)? "1 board done" means you had one or more physical copies of the board. [rough estimation, positive integer],9. Approximately how many boards have you done with other packages? [rough estimation, positive integer],10. What OS would you prefer to do your pcb layouts on (assuming your favorite layout tool is/would be available on it)? [one of: (GNU/)Linux, *BSD, OSX, windows, other; if you like more, select the one you would spend most time on!],, \ No newline at end of file Index: tags/1.2.7/doc/devlog/20162601/poll.csv =================================================================== --- tags/1.2.7/doc/devlog/20162601/poll.csv (nonexistent) +++ tags/1.2.7/doc/devlog/20162601/poll.csv (revision 13657) @@ -0,0 +1,10 @@ +0,50,yes,yes,no,no,no,1,2,Linux +10,40,no,n/a,no,yes,n/a,20,2,Linux +0,5,n/a,no,no,no,no,20,4,Linux +5,20,no,no,no,yes,no,5,20,Linux +0,0,n/a,n/a,no,no,no,10,0,Linux +0,80,yes,yes,no,no,no,15,0,Linux +50,80,no,no,no,yes,n/a,30,100,OSX +20,75,no,no,no,yes,yes,15,3,Linux +0,8,yes,yes,yes,yes,no,2,1,Linux +0,2,yes,yes,no,no,no,8,4,Linux Index: tags/1.2.7/doc/devlog/20162601/poll.html =================================================================== --- tags/1.2.7/doc/devlog/20162601/poll.html (nonexistent) +++ tags/1.2.7/doc/devlog/20162601/poll.html (revision 13657) @@ -0,0 +1,24 @@ + + +
        1. How many of your boards REQUIRE burried or blind vias? [percentage] +2. How many of your boards could BENEFIT burried or blind vias? [percentage] +3. When your board REQUIRED them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no] +4. When your board could BENEFIT using them, do you more often find a workaround to stick with pcb instead of switching to another design tool? [yes/no] +5. Have you ever tried pcb-rnd? [yes/no] +6. Would you try pcb-rnd if it offered blind/burried vias? [yes/no] +7. Would you consider switching to pcb-rnd if it offered blind/burried vias? [yes/no] +8. Approximately how many boards have you done so far with pcb (pcb mainline/branches/forks included, using gschem/gnetlist not required)? "1 board done" means you had one or more physical copies of the board. [rough estimation, positive integer] +9. Approximately how many boards have you done with other packages? [rough estimation, positive integer] +10. What OS would you prefer to do your pcb layouts on (assuming your favorite layout tool is/would be available on it)? [one of: (GNU/)Linux, *BSD, OSX, windows, other; if you like more, select the one you would spend most time on!] + +
        050yesyesnonono12Linux +
        1040non/anoyesn/a202Linux +
        05n/anononono204Linux +
        520nononoyesno520Linux +
        00n/an/anonono100Linux +
        080yesyesnonono150Linux +
        5080nononoyesn/a30100OSX +
        2075nononoyesyes153Linux +
        08yesyesyesyesno21Linux +
        02yesyesnonono84Linux +
        Index: tags/1.2.7/doc/devlog/20162601/poll.tsv =================================================================== --- tags/1.2.7/doc/devlog/20162601/poll.tsv (nonexistent) +++ tags/1.2.7/doc/devlog/20162601/poll.tsv (revision 13657) @@ -0,0 +1,10 @@ +0 50 yes yes no no no 1 2 Linux +10 40 no n/a no yes n/a 20 2 Linux +0 5 n/a no no no no 20 4 Linux +5 20 no no no yes no 5 20 Linux +0 0 n/a n/a no no no 10 0 Linux +0 80 yes yes no no no 15 0 Linux +50 80 no no no yes n/a 30 100 OSX +20 75 no no no yes yes 15 3 Linux +0 8 yes yes yes yes no 2 1 Linux +0 2 yes yes no no no 8 4 Linux Index: tags/1.2.7/doc/devlog/20170205_schimp.html =================================================================== --- tags/1.2.7/doc/devlog/20170205_schimp.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170205_schimp.html (revision 13657) @@ -0,0 +1,37 @@ + + +

        pcb-rnd devlog

        + +

        what's needed for schematics -> pcb-rnd

        +

        by Igor2

        +

        +If a path between a schematics capture program and pcb-rnd is to be implemented, +the following information needs to be passed: +

          +
        • schematics -> pcb (forward annotation) + Any file format the schematics tool prefers and delivers at least this + set of information: +
            +
          • Each component/part needs an unique identifier, a "refdes", e.g. R1, U4. +
          • Each pin/pad needs an unique identifier within it's component/part, so at the end "U4-3" uniquely identifies pin 3 of component U4. +
          • Each component/part needs a footprint (a free form text). Optionally arbitrary user specified key=value pairs per part can solve this and a lot more. +
          • A list of named networks. Optionally with user specified key=value pairs per network (less important here). +
          • A list of component-pin pairs per network. +
          • The netlist can be flat or hierarhic. +
          + +
        • pcb -> schematics (back annotation) + pcb-rnd emits a netlist patch described + here , but it + could emit any other format the schematics tool needs. The schematics tool + would need to understand the following concepts while reading a back + annotation file: +
            +
          • Unique part refdes and pin number, as above +
          • Named networks, as above +
          • "this is how the network looked like when we started" (net name, list of pins) +
          • "the user removed this pin from that network" operation +
          • "the user added this pin from that network" operation +
          • optional: "the user changed this key=value pair of this part" +
          +
        Index: tags/1.2.7/doc/devlog/20170212_ecosys.html =================================================================== --- tags/1.2.7/doc/devlog/20170212_ecosys.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170212_ecosys.html (revision 13657) @@ -0,0 +1,11 @@ + + +

        pcb-rnd devlog

        + +

        The FOS EDA ecosystem and pcb-rnd in it

        +

        by Igor2

        + +

        +This article has been moved to + +the knowledge pool. Index: tags/1.2.7/doc/devlog/20170213_edacore1.html =================================================================== --- tags/1.2.7/doc/devlog/20170213_edacore1.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170213_edacore1.html (revision 13657) @@ -0,0 +1,11 @@ + + +

        pcb-rnd devlog

        + +

        "Edacore" minimum commons

        +

        by Igor2

        + +

        +This article has been moved to + +the knowledge pool. Index: tags/1.2.7/doc/devlog/20170213_edacore2.html =================================================================== --- tags/1.2.7/doc/devlog/20170213_edacore2.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170213_edacore2.html (revision 13657) @@ -0,0 +1,11 @@ + + +

        pcb-rnd devlog

        + +

        "Edacore" - extras

        +

        by Igor2

        + +

        +This article has been moved to + +the knowledge pool. Index: tags/1.2.7/doc/devlog/20170405/Makefile =================================================================== --- tags/1.2.7/doc/devlog/20170405/Makefile (nonexistent) +++ tags/1.2.7/doc/devlog/20170405/Makefile (revision 13657) @@ -0,0 +1,2 @@ +umbrella.svg: umbrella.dot + dot -Tsvg umbrella.dot > umbrella.svg \ No newline at end of file Index: tags/1.2.7/doc/devlog/20170405/umbrella.dot =================================================================== --- tags/1.2.7/doc/devlog/20170405/umbrella.dot (nonexistent) +++ tags/1.2.7/doc/devlog/20170405/umbrella.dot (revision 13657) @@ -0,0 +1,50 @@ +digraph g { + + + subgraph cluster_1 { + label="umbrella" + pcbrnd [style=filled fillcolor=green label="pcb-rnd" height=2 width=2] + edakrill [style=filled fillcolor=green height=1.5 width=1.5] + tedax [style=filled fillcolor=green] + cschem [style=filled fillcolor=red height=1.5 width=1.5] + genxproj [style=filled fillcolor=red] + } + + subgraph cluster_2 { + label="legend" + l1 [style=filled fillcolor=green label="released,\nready"] + l2 [style=filled fillcolor=red label="planned"] + l3 [label="3rd party,\nexternal"] + } + + + pcbrnd -> edakrill [dir=both weigth=100] + pcbrnd -> cschem [dir=both weigth=100] + pcbrnd -> tedax [dir=both weigth=100] + genxproj -> pcbrnd [dir=both weight=50] + genxproj -> cschem [dir=both weight=50] + cschem -> tedax [dir=both weigth=100] + + cschem -> edakrill [dir=both constraint=false] + + edakrill -> tedax [dir=both weight=50] + + + pcbrnd -> kicad [dir=both] + genxproj -> kicad [dir=both] + edakrill -> kicad [dir=both] + + pcbrnd -> gschem [dir=both] + genxproj -> gschem [dir=both] + edakrill -> gschem [dir=both] + + pcbrnd -> eagle [dir=both] + edakrill -> eagle [dir=both] + + tinycad -> pcbrnd + genxproj -> tinycad [dir=both] + + mentor -> pcbrnd + pcbrnd -> fidocadj [dir=both] + +} Index: tags/1.2.7/doc/devlog/20170405/umbrella.svg =================================================================== --- tags/1.2.7/doc/devlog/20170405/umbrella.svg (nonexistent) +++ tags/1.2.7/doc/devlog/20170405/umbrella.svg (revision 13657) @@ -0,0 +1,211 @@ + + + + + + +g + +cluster_1 + +umbrella + +cluster_2 + +legend + + +pcbrnd + +pcb-rnd + + +edakrill + +edakrill + + +pcbrnd->edakrill + + + + + +tedax + +tedax + + +pcbrnd->tedax + + + + + +cschem + +cschem + + +pcbrnd->cschem + + + + + +kicad + +kicad + + +pcbrnd->kicad + + + + + +gschem + +gschem + + +pcbrnd->gschem + + + + + +eagle + +eagle + + +pcbrnd->eagle + + + + + +fidocadj + +fidocadj + + +pcbrnd->fidocadj + + + + + +edakrill->tedax + + + + + +edakrill->kicad + + + + + +edakrill->gschem + + + + + +edakrill->eagle + + + + + +cschem->edakrill + + + + + +cschem->tedax + + + + + +genxproj + +genxproj + + +genxproj->pcbrnd + + + + + +genxproj->cschem + + + + + +genxproj->kicad + + + + + +genxproj->gschem + + + + + +tinycad + +tinycad + + +genxproj->tinycad + + + + + +l1 + +released, +ready + + +l2 + +planned + + +l3 + +3rd party, +external + + +tinycad->pcbrnd + + + + +mentor + +mentor + + +mentor->pcbrnd + + + + + Index: tags/1.2.7/doc/devlog/20170608_github.html =================================================================== --- tags/1.2.7/doc/devlog/20170608_github.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170608_github.html (revision 13657) @@ -0,0 +1,77 @@ + + +

        pcb-rnd devlog

        + +

        How github promotes confusion

        +

        by Igor2

        +

        +Pcb-rnd is hosted in an svn repository (at svn://repo.hu/pcb-rnd) - +there is no official git or hg or bazaar repository. As +it is free software, people are encouraged to make and distribute copies. +Majority of the cases such behavior is beneficial for users: e.g. when +a Linux distro packages pcb-rnd, helping its users to run it or even +when an user makes a mirror repository, clearly marked as a mirror. +

        +I also encourage everyone who doesn't like the ways of pcb-rnd but does +like the code, to fork the project: copy the repository or the code, +rename it, make whatever modification and publish it. +

        +There is only one use pattern I find harmful: when someone makes a +fork, clone or mirror without clearly marking it being a copy. Unfortunately +this has happened on github and gitlab: an user cloned a very old +version of pcb-rnd and called it simply pcb-rnd. This matters because +popular web search engines assign high scores to projects hosted on +github. A potential user who hears about pcb-rnd not from us (the dev team), +will not know the URL of the project and will use a web search, which then +promotes github from where he will pull and old version. He may later read +the doc and figure it's just a random copy of an old version, and go +and get the latest from the official site, but the point is: +

          +
        • he has wasted some time on the wrong version +
        • other than being a "honey pot" for unlucky users, such an old copy does not have any benefit for the users or developers +
        • the only potential winner of such a deal is github, harvesting some more clicks +
        +

        +But the real lesson learned for me was not this, but how github is not +motivated in avoiding such confusion. +

        +The first meta text on the github page says: +

        +"Contribute to pcb-rnd development by creating an account on GitHub."
        +
        +This is clearly a lie - that's not how you contribute - instead, +contribution is via svn commits and IRC. Unfortunately google picks up +the same setence so this false information is on the first page of +a google search on "pcb-rnd". +

        +I first tried to contact the author to ask him to rename his fork; github +is not helping much in that: there's no contact info for the user, not +even a captcha-protected email or "send a message" form. I'd expect such +a service was designed to help people work together, which does include +contacting others. +

        +So I went on and found the problematic user's email from other sources. +I tried to contact him a few times but he ignored my attempts. +

        +After seeing an actual user getting confused on the said github project, I +decided to contact github and see if they are willing to help in renaming the +repository to avoid confusion. Well, they are not. I got an answer from the +support that made it clear they did not even read the request, just copied +some stock answer. After getting through that layer,they said I should file +a DMCA take-down request; I asked them whether they think it would apply in case +of GPL projects but they said they can't answer that and I should consult a +lawyer! But after reading their own material on DMCA it's pretty clear they +would simply do nothing even if the said user actually committed copyright +infringement. +

        +So my conclusion is: if you ever want to get a project hosted, do NOT +choose github, because: +

          +
        • the support doesn't help at all (they don't even read what you write, just send some semi-automatic answer first) +
        • they are not really interested in serving the community or the users, but in being the biggest, getting the most clicks - if the path to that is maintaining confusion, that's fine for them +
        • they don't seem to care much about users who are not registered or not wanting to do pull requests - to an extent that contacting authors is pretty much impossible as an "outsider" +
        +Looking at gitlab, I see similar tendencies. Repo.or.cz looks a bit better, +at least there the owner of a repo has an email address. +

        +(All the above is obviously my personal opinion based on my personal experience.) Index: tags/1.2.7/doc/devlog/20170617_subc.html =================================================================== --- tags/1.2.7/doc/devlog/20170617_subc.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170617_subc.html (revision 13657) @@ -0,0 +1,77 @@ + + +

        pcb-rnd devlog

        + +

        subcircuit roadmap: element names

        +

        by Igor2

        + +
        +> So that brings up another question: how is the displayed element name
        +> going to change behavior in future versions of pcb-rnd?
        +
        + + +Good question. I've been thinking about this a lot lately. +

        +

        The current situation in full details

        +

        +there are exactly 3 pcb text objects attached to each pcb element object. +A text object has size, coordinate, font ID, rotation and string (plus +the usual background info like rtree entry). Although you see only one of +these at any given time, the code maintains all three. +

        +And although the coordinate and rotation and size and font, or in other +words, everything but the string, need to be the same, we still store +all these data 3 times... Every code that needs to touch an element text +also needs to repeat all these ugly hacks; like the code that can move an +element text really needs to move 3 to keep all coords in sync. +

        +On one hand I like to be able to globally change whether we show refdes or +value, but on the other hand I often want to see both. And even more: it's +a different use case to see data on the screen or see the artwork on silk. +

        +

        So my plan for subcircuits

        + +
          +
        • 1. We will be able to have as many text objects as the user wants, on +whichever layer (including mask or even paste) + +
        • 2. we'll have some metadata for each object (text objects included) that +tells the role of the object. + +
        • 3. The role won't be one of 3 sacred roles some holy priests invents in +the initial implementation, but user defined. The default convention +obviously will be our usual 3 roles: refdes, value, footprint name. + +
        • 4. Because of 2. and 3., we will be able to identify what objects make up +a refdes; these objects can be multiple texts, rectangles, can be on silk +or any other layer. For example if I don't have silk but have mask, I +could move my refdes' to mask. Or even to copper. + +
        • 5. The UI... we'd have two different things there: + +
            +
          • We'd have some GUI aid to display data on some overlay UI layer, +independenlty of whether the data land on silk or not. So you'd be able +to look at the value of all components on screen, without this affecting +the silk layer in any way. This feature would be close to what we have now +in the sense that you could globally tell it which role to show; but more +like a set of checkboxes than a radio button: I often want to see both +refdes and value. + +
          • Then we'd have some per-subcircuit control over which elements are +hidden, so you won't need to get all them on silk. E.g. you'd show refdes +and element-outline related objects but hide the others. This would be +subcircuit-local, we wouldn't have a global setting for this. We could +still have scripts and actions to make mass-changes possible, but the +actual bit for show/hide is stored per subcircuit instance. This would let +us print the value of some important elements, or even all resistors while +none of the ICs. +
          +
        + +

        + +Most of this wouldn't happen in the first implementation of subcircuits +but would be added gradually. + Index: tags/1.2.7/doc/devlog/20170629_subc.html =================================================================== --- tags/1.2.7/doc/devlog/20170629_subc.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170629_subc.html (revision 13657) @@ -0,0 +1,158 @@ + + +

        pcb-rnd devlog

        + +

        subcircuit: how does this clean things up today

        +

        by Igor2

        + +

        pcb_data_t

        +

        +Subcircuits use pcb_data_t to store their children objects. This is the +same struct that pcb_board_t uses for a PCB board and the same struct that +makes up a paste buffer. +

        +Elements (footprints) on the other hand were designed to use custom structs. +That is the reason for all the restrictions on what an element can be built of. +These element-restrictions do not exist for +subcircuits. +

        +This helps cleaning up the broken internal data model of original pcb: +there's only one way to make a new level of the data tree for holding +drawing primitives, and it is pcb_data_t. This lets the code traverse +the tree from the root toward the leaves. + +

        parents

        +Symmetrically, each object now properly references its parent. Today this +lets the code: +
          +
        • traverse the data tree from a leaf toward the root +
        • decide whether a given object is part of a subcircuit, buffer or a board +
        +

        +This is another important step in cleaning up the broken internal data model +we inherited. + +

        uid

        +

        +Some exporters need to build a list of unique element references - that is, if +the board uses 15 instances of 1206, the exporter would need to recognize that +and store only one copy and 15 references. This is done with a special hashing +algorithm that "reverse engineers" the elements and try to figure if two elements +are really the same, even tho they are rotated. +

        +With subcircuits, this won't be done in such a complicated, indirect way because +subcircuits get an unique ID when they are born and copies share the same UID. +The UID is "globally" unique; that means it's not only unique within a board +or within a library or within an installation or system. If users share their +subcircuit libs, the same 1206 got from the same lib will have the same UID +on all copies and boards and it will be trivial to determine whether two +subcircuits are really the same. + +

        aux layer and vectors

        +

        +Another crucial misfeature of elements is the lack of rotation and mirror +information. That is, if the user places an element on a board and the element +is rotated or moved to the other side, it is just modified in the data model +as if it was the natural orientation of the element. In other words, looking +at an element in the original geda/PCB model, it is impossible to +reliable determine the rotation. All the pick&place exporters are just +making educate guesses with a lot of limitations, e.g. only N*90 degree +rotations can be detected properly. +

        +In subcircuits there is a layer called 'aux', which contains line objects +labelled with attributes. The aux layer doesn't turn into copper, silk, paste +or mask, it's rather a documentation layer. The lines it hosts undergo all +transformations the host subcircuit undergoes: if the parent is rotated, +all lines are rotated. When a new subcircuit is created, a few line objects +like the origin point and two lines (unity-vectors in X and Y directions) are +automatically placed on the aux layer. +

        +Whenever the rotation needs to be determined, the code can just look at what +happened to these X and Y unity vectors knowing how they looked originally and +calculates the rotation to a fraction of a degree. Without any heuristics or +guesses. +

        +How is it better than just storing the transformations: +

          +
        • more reliable; any subc-global code needs to execute on all objects already; + storing transformation info separately would mean all transformation code + needs to be revised and the metadata update added. Miss one, and the + metadata stats to lie. With this trick, it's impossible to miss one. +
        • more extensible: specific exporters may need new points or vectors for + whatever reason, e.g. a custom centroid for a pick&place, or even + a custom rotation vector. In this model, these are just more lines + with new, custom, plugin-specific attributes that are then automatically + handled by existing code, without having to register anything anywhere. + This is how plugins in pcb-rnd can extend infrastructure without any + footprint in core +
        • one unity-vector could reveal rotation; two can reveal rotation and + mirroring. We do not scale subcircuits (yet?), but two vectors could + be used to measure the scale as well. Which means if we later implement + scaling, it will just work, without having to add another set of metadata, + without having to worry now what we'd need to add to get scaling work later. +
        + +

        bound layers

        +Paste buffers and subcircuits don't really have a layer stack, because they +are board-independent. Paste buffers need to be able to copy random objects +on random layers from one board to another, even if the boards have different +layer stacks, in a sensible way. The original code (and current mainline code) +has hardwired layer references in pcb_data_t, which means this is impossible; +any paste-buffer copy will work properly only if the source and target boards +have the same layer stack. +

        +A sensible way is to solve this problem is to remember layer binding patterns +instead of specific fixed layers. A fixed layer reference is like "layer 4" and +is always referring to the current layer stack. One board may have bottom silk as +layer 4, while another board may have an internal copper layer or the outline layer +as layer 4. +

        +A layer binding pattern is something like a recipe on how to find the best +match for a layer, e.g. "a top copper layer", or "the second internal copper +layer counted from the top copper layer", or "a positively drawn mask layer on +the top side". Subcircuits and buffers in pcb-rnd use such layer binding patters. +When a board object becomes part of a subcircuit or is copied into a paste +buffer, the code abstracts the board specific layer binding into such a generic +pattern. When the subcircuit or buffer is then copied back to a board, the +code finds the best fit layer. This is called layer resolution. +(The original layer binding patterns are also kept in subcircuits, so multiple +abstractions and resolutions won't degrade the match pattern.) + +

        on-screen indication of subc

        +

        +Subcircuits are optionally indicated with a dashed rectangle at their bounding +box and their origin diamond. Old elements rely on silk screen outline and +sometimes largish elements without a clear silk screen box may include remote +pins that make the element much larger than they first appear. The only way +to figure the bounding box is grabbing the element - which most often happens +by accident, not suspecting some free space in the middle of the board is really +under a large element. This problem is fixed with the subcircuit bounding box +visualization. +

        +Two new virtual layers are introduced: +

          +
        • one controls whether the subcircuit bounding box and origin should + be shown; when hidden, subcircuits are "locked": they don't react on moving/rotating/etc. + which makes it easy to edit other objects under largish subcircuits; Note: + for elements, the same could be achieved by turning off the silk layer or + pins/pads; but that means side effects; the new system for subcircuits is + more orthogonal, turning off the virtual layer of subcircuits won't hide + pins or silk as a side effect. + +
        • the other controls whether objects being part of subcircuits are shown + or not; this is similar to the old pins/pads virtual layer with elements, + except it works on all subcircuit-donated objects, not just pins and pads. +
        + +

        layer side effects

        +

        +When an element is rendered, a thin black diamond is drawn on screen. This +diamond looks like if it was on the silk screen - it always has the same +color as the corresponding silk screen. +

        +Subcircuits use a separate virtual layer ("subcircuit parts") and +a different color (red by default) for drawing the diamond and a dashed +bounding box around the subcircuit. This makes it easier to see what's +auto-generated eye-candy and what's really on the silk screen + + Index: tags/1.2.7/doc/devlog/20170711_elem.html =================================================================== --- tags/1.2.7/doc/devlog/20170711_elem.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170711_elem.html (revision 13657) @@ -0,0 +1,143 @@ + + +

        pcb-rnd devlog

        + +

        element-resrtictions: why is it not a file format issue?

        +

        by Igor2

        + +

        +Because this topic comes up from time to time, and by now I have actual +data (implementation costs) on it, I decided to write a short analysis on: +

          +
        • why we have the "element restrictions" problem in the first place + +
        • different ways to resolve the "element restrictions" problem + +
        • measured (or partly estimated) cost of some of these + +
        • conclusion: why simply changing the element file format won't help +
        + +

        +Note: A solution (including a global data srtuct cleanup) is +being implemented in pcb-rnd. + +

        +A random quote from the geda-user mailing list: +

        +> Maybe you composed the footprint entirely of atoms that are not elegible
        +> to be included in a pcb footprint. Due to restrictions in the file
        +> format,
        +
        + +

        +It is a common pattern that users express element restrictions are really +file format restrictions. Unfortunately this is not the case. Unfortunately, +because fixing a mere file format would be much cheaper. + +

        The problem

        +

        +Elements contain element-specific drawing primitives and the code has +special casing for these in every little corner. Extending/replacing the +file format is a relatively small effort, affecting a small part of the +code base. Adding support for polygons, copper lines, vias, arbitrary +text, etc. in elements is a huge effort because it really touches +everything from the famous find.c through all drawing pimitive holding +data structures to draw.c. +

        +When you see a silk line or silk arc on screen, produced by an element, it +is not really just a line or arc. It is really an element-line and an +element-arc. Yes, these are separate, special drawing primitives that work +only in elements; elements can't consists of plain line or arcs. Majority +of the code simply has an "if" or a separate "case" branch or a separate +callback function for handling each of these element-* object. The data +structs don't hold a list of drawing primitives; they hold a list and an +rtree of lines, another list and rtree of arcs, etc. And yes, this means +a specific element-line and element-arc list within elements. Plus these +element-objects ignore layers: instead of being on a layer, they are +either on the top or on the bottom side. For silk and pads it's fine, but +if you want outline, paste, inner copper layers, that's 1000 other special +casing. +

        +For example if you wanted to have non-pad copper lines in a pcb footprint, +extending the existing code base, you'd need to: +

          +
        • decide to introduce an element-copper-line drawing primitive (estimated +cost: at most an hour to add it in all the central lists of magic numbers +and names) + +
        • go and grep the code for handling plain old lines in any way, and copy +all code and introduce an element-copper-line drawing primitive (estimated +cost: days or weeks!!!) + +
        • reimplement the which-side-is-this-on hack for your new object +(estimated cost: many hours or days) + +
        • add a printf in file.c and a yacc/lex section for the new drawing +primitive (estimated cost: at most 1..2 hours) + +
        +

        +(Or you can chose to rather implement a generic object grouping feature of +the existing primitives: line, arc, text, poly, via, and say element-* +special casing should be just removed as groups can replace elements. This +is what I am doing in pcb-rnd with subcircuits, see below) +

        +This is why, contrary to the popular belief, simply changing the file +format to xml or json or whatever-else won't magically fix the problem. +Instead rewriting 1/3 of the code base would. Then whether you keep the +.fp/.pcb format (and upgrade it to handle the new situation) or introduce +a new file format is a tiny implementation detail. +

        +Note: I'm saying this after implementing a new native file format +(lihata), working on half dozen alien board/footprint file formats _and_ +being halfway through resolving the element restrictions by replacing +elements with subcircuits in pcb-rnd. + + + +

        evidences: data

        + +

        +Below I'm sharing objective data on this topic. Talking in pcb-rnd net +development times, implementing support for a new footprint file format is +ranging from a few hours to 1..2 days, if the format is reasonable. For +example implementing a working plugin for tEDAx that loads netlist, loads +and saves footprints took less than 14 hours total. Note: this is the time +spent on a new, non-native format _and_ a netlist load. Extending the +.fp/.pcb format would be way cheaper, so you can take this as a very +permissive upper estimation. +

        +Implementing half of the subcircuits took me 85 hours so far: we have +generic grouping, with dynamic layer binding; we can save and load the +result; we can have any object on any layer; we keep track of +rotation/mirroring/scaling; we have and unique ID to keep track on what +subcircuit is cloned from what other subcircuit. What's still missing for +replacing elements, and we will have in the next development cycle: +"terminals" (turning any copper object into a pin or pad). +

        +By the time subcircuits will be able to fully replace footprints/elements, +I estimate total expense between 180..200 hours. And these "low" numbers +are possible only because I had already invested more than 130 hours in +the layer rewrite before I started on subcircuits. If we account the the +element-restriction-resolving parts of the layer rewrite in this effort, +the final "element rewrite" cost would be over 250 hours (from which more +than half are already spent and only the other part is estimation). + + +

        Conclusion

        +

        +250 hours of subcircuits+layers (half spent, half estimated) vs. 14 hours +of a file format (spent). +

        +So a [new footprint file format + new netlist format] was less than 6% of +the half-measured-half-estimated cost of solving the element restriction +problem in case of pcb-rnd. +

        +Of course different projects and different developers would make different +choices, and with subcircuits I am really doing the most flexible thing +possible: i just decided to really clean up the data model, not just hack +in polygons and copper lines. +

        +But I still say that with even a cheaper, more hackish element upgrade the +file format issue is only 5..15% of the whole problem. Index: tags/1.2.7/doc/devlog/20170712_native.html =================================================================== --- tags/1.2.7/doc/devlog/20170712_native.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170712_native.html (revision 13657) @@ -0,0 +1,70 @@ + + +

        pcb-rnd devlog

        + +

        Native file format vs. alien file formats

        +

        by Igor2

        + +

        Terminology

        +

        +All board, subcircuit, fonts and footprint file formats are implemented +in plugins. Plugins are optional - it is even possible to compiel +pcb-rnd with all file format support turned off. The only format core +supports is the in-memory representation, which is never saved to a file +directly. +

        +There are 3 type of plugins doing file format read/write (doing the +conversion between the in-memory representation of core and actual file +formats): +

          +
        • export_ plugins: the in-memory data is exported to a file format without + any hope that it could be imported back again; e.g. exporting a board + as png or svg. This operation often lose a lot of metadata - the + result looks good but deep down it doesn't mean the same + as the in-memory representation. +
        • import_ plugins: the output of some external program is imported into + memory; this operation is not meant to be lossless either and usually + covers only a small portion of all data. Typical example: + importing a netlist. +
        • io_ plugins: save data from memory, load data to memory; + save-load round trips should produce acceptable results, although + lossless operation is usually not assumed in either load or save + (except for the native format). +
        +

        +Orthogonal to this, pcb-rnd terminology native file format and +alien file format is also defined. There is always one io_ plugin +that is required to perform perfect, lossless save and load. This +plugin, and its file format is called native, while all other io +plugins are called alien. +

        +The only difference is the above requirement; in any other aspect io +plugins are all equal. It is possible that an alien io_ plugin also +happens to produce perfectly lossless round trips. It is possible to +compile pcb-rnd with the native format disabled. + +

        Rationale

        +

        +As the core of pcb-rnd is developed, the in-memory representation of the +data model changes. Alien formats are usually formats defined for other +projects; these formats try to track changes in the data model of those +other projects. If pcb-rnd had to keep perfect compatibility with any of +those, that'd mean pcb-rnd core and data model couldn't evolve +naturally, but would be bound to and restricted by that other project's +design. To avoid that, and to guarantee that pcb-rnd has a file format +that supports all features of core at any given time, a pcb-rnd-specific +(native) file format. +

        +In theory pcb-rnd could support multiple native file formats. In +practice, it would be an overhead in development: any change or new +feature in core would need to be tracked by more than one io plugin. +

        +On the other side, having the second format as alien has no real +drawback for the end user long term. Assuming the second format is a +pcb-rnd-specific format too, and pcb-rnd developers are free to change +the format specification, even as an alien format it will tend to track +core features eventually. The only difference is that it is not +guaranteed that the latest core features are always immediately +accessible in the second, non-native format. + + Index: tags/1.2.7/doc/devlog/20170712_sql.html =================================================================== --- tags/1.2.7/doc/devlog/20170712_sql.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170712_sql.html (revision 13657) @@ -0,0 +1,89 @@ + + +

        pcb-rnd devlog

        + +

        why not sql?

        +

        by Igor2

        +

        +Question on geda-user: +

        +> If you're going to replace the entire data model, why not use SQLite?
        +> This would give you an almost free replacement for the convoluted and
        +> buggy rtree and undo implementations as well as providing file format
        +> accessible to almost every language anyone might care to use.
        +
        + +

        +First of all: my goal is exactly not +to rewrite the whole data model in one big go, but to gradually upgrade it +and slowly replace elements with subcircuits while keeping everything +compatible and working all the time. I also want to keep the good part and +replace the bad parts only. Glib is already replaced, and I am going to +keep rtree. If you want to learn more about the process, please read the +oldest devblog entry I linked in the other mail. + +

        +Why not SQL: because I prefer simplicity, portability and want to +cut down mega-lib dependencies instead of introducing more of them. Sqlite +is 50k sloc, while the complete pcb-rnd source is 200k sloc. If you want +to use or contribute to projects where this does not matter, please chose +gEDA/PCB or kicad. + +

        +Purpose/functionality/capability: my opinion is that sqlite, and sql in +general would be an inefficient, bloated solution that would attempt to +fix something that's not really broken, taking away energies from fields +where we do have things to fix or implement. In return sql is not that +efficient on spatial data as people love to believe^1. Just because it's +huge and popular and everyone tries to use it doesn't mean it's the good +solution for every possible problem. + +

        +"Don't fix what's not broken" (especially not with a worse +solution): + +

          +
        • we already have a very good native file format, lihata, there's 0 reason +to replace it. The lihata parser is very small, it's trivial to make +bindings to from any language or even reimplement it in any language. +Contribute bindings if your favorite language doesn't have support. If +you can't stand lihata, just don't use pcb-rnd. + +
        • the rtree code works fine, there's no known bug at the moment. If you +know about bugs, be constructive: report them, patch them, commit the fix. + +
        • same for the undo engine: no known bug. +
        + +

        +(Note: I have plans to rewrite parts of the undo engine to make it more +extensible from plugins (cost estimation: 20..30 hours), but it's somehwat +unrelated.) + +

        + +

        Conclusion

        + +If you want sqlite, that's not pcb-rnd, that's another project. Levente +once started such a project +but it didn't get too far - maybe go and +pick that up. Or try selling the idea to mainline or kicad. Or fork +kicad or mainline or pcb-rnd, rename, add sql, see if users are really +turned on by it. You said sqlite is an "almost free replacement", so +this must be a real quick project for you. + + +

        Footnote

        + +

        +^1: we did test that once for a challenge24 task, with postgresql's spatial +support and the result was so disappointing that we ended up implementing +a custom solution in C. If you disagree, and think sql will be more +efficient than rtree: go and implement a script that loads a complex board +into sql and execute and time 1M screen-searches with the rtree code and +the sql version. Although other disadvantages of sql would make it a no-go +for pcb-rnd even if you could get similar efficiency, it'd be still an +interesting result to achieve! + + + Index: tags/1.2.7/doc/devlog/20170809_undo.html =================================================================== --- tags/1.2.7/doc/devlog/20170809_undo.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170809_undo.html (revision 13657) @@ -0,0 +1,113 @@ + + +

        pcb-rnd devlog

        + +

        undo cleanup

        +

        by Igor2

        +

        +I'm announcing a new minilib called libuundo that provides an +application-agnostic undo mechanism. +

        +Doc: http://repo.hu/projects/libuundo/ +

        +Source: svn://repo.hu/libuundo/trunk +

        +The rest of this mail is dealing with "why do I think we need that" and +"how does it solve those problems". + + +

        What's wrong with pcb-rnd's (and pcb's) current undo code?

        +

        +The current undo code (as of pcb-rnd r10665 and pcb 4.0.0) is too +centralized. There is a list of undoable actions and associated +undo-data declared in a central place (undo.c) in core. If any part of the +code introduces a new undoable action, it's not just that that part of the +code starts to depend on undo, but undo starts to depend on that part of +the code too, because half of the implementation needs to go in undo.c. +This does not help making the code modular. +

        +pcb-rnd's modularity also heavily depends on plugins. The above setup +works only as long as new undoable actions are never programmed in +plugins. This is a severe limitation on what code can be moved out from +core to plugins and forces some new code to go in core instead of a +plugin. Or alternatively forces plugins to implement some actions that are +not undoable. +

        +(This does not affect the case when the plugin operation can be carried +out exclusibely by calls to existing core function that already have undo +capability. While this is a common pattern, we also have the other pattern +where atomic undoable functionality need to be implemented in plugins) +

        +Another problem related to plugins is that undo.c has no privisions for +unloadable plugins - that is, even if plugins could register undo items on +the list, once the plugin is unloaded we'd have a broken undo list. With +the current code it would be hard or impossible to detect this condition, +so the only safe option would be to clear the whole undo history any time +any plugin is unloaded. +

        +Two levels merged: undo.c contains both the high level "maintain a list of +undo/redo items" and the low level "how to undo this specific operation" +functions and their undo data. Because of the undo data, and because the +undo list item is basically a big union of all those data, the two levels +can not be separated, the high level needs to know the struct sizes of the +low level. With the current way the data is stored +(uniform-item-width array with realloc) this can not be fixed. +

        +Finally, reusability and license: undo.c is GPL2+, which is totally fine +for pcb-rnd and pcb. Other applications could benefit from the high level +part of the undo mechanism. It makes sense to copy the code from pcb-rnd +(or pcb) or even make this high level part a reusable lib. However, GPL2+ +might be too restrictive for applications licensed even under other FLOS +software licenses. Because of the history of the project and potentially +many authors of the file, it's probably not feasible to try to change the +license. + + +

        How does libuundo solve these

        +
          +
        • reuse: libuundo is a very small library, independent of pcb-rnd or pcb; +the API is small too, it's easy to reuse in random applications + +
        • license: libuundo is written from scratch, under LGPL2+, which is more +liberal on library-reuse. The library is single-author so far, so it's +easy to extend licensing (e.g. dual license if a project finds even LGPL +too restrictive) + +
        • levels: libuundo implements the high level only, the low level is up to +the caller; the API is baed on function callbacks provided by the +application + +
        • variable item data size: each undo item can have a different sized +user-data + +
        • modularity: because of the function callbacks, the low level undo code +does not need to be centralized; plugins can implement their undo/redo +without having to place code in core + +
        • plugin provisions: without libuundo implementing or using any plugin +system, it provides an API that lets the application track which plugin +registered with undo item. It is possible to check the undo list upon a +plugin unload and do a selective clear. +
        + +

        Plans in pcb-rnd regarding to libuundo

        +

        +I've already split the high level and low-level, except for the structs, +in pcb-rnd. +

        +The next step will be to finish this split by removing most of the code +for the high level and use libuundo instead. +

        +The old, centralized undo will become a single "operator" in the new +system. Thus we will get the same functionality mostly working the same +way, but already being able to register new undo operators even from +plugins. +

        +Later on, the old, centralized undo will be slowly rewritten so that each +undoable action will be a separate uundo operator placed in the module +that is responsible for it. Eventually this will remove the centralized +low level part. +

        +(Obviously I think mainline pcb and gschem could benefit from a similar +move, but I am not making any suggestion) + Index: tags/1.2.7/doc/devlog/20170813_prim.html =================================================================== --- tags/1.2.7/doc/devlog/20170813_prim.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170813_prim.html (revision 13657) @@ -0,0 +1,123 @@ + + +

        pcb-rnd devlog

        + +

        drawing primitives roadmap

        +

        by Igor2

        + +

        1. current situation

        +

        +A drawing primitive is an atomic object that the board (e.g. layers) is +built of. gEDA/pcb has the following drawing primitives: +

        + +
        primitive scope limitation +
        line layer none +
        arc layer none +
        text layer supported only one font +
        polygon layer none +
        via global same ring (pad) on all layers; limited number of shapes; no bbvia in pcb-rnd yet +
        element global can host only element-* objects, pins and pads +
        element-line element only on silk +
        element-arc element only on silk +
        element-text element only on silk, only one of value, refdes and device +
        pad element only line shape, only on top or bottom copper layer +
        pin element only via shape +
        +

        +What pcb-rnd has at the moment (summer of 2017, version 1.2.4) is basically +the same, except full multi-font support and a basic support for subcircuits: + +
        primitive scope limitation +
        text layer none +
        subcircuit global can not interact with the netlist +
        +A subcircuit can hold line, arc, text and polygon on any layer and vias. + +

        2. goal

        +The following table shows where pcb-rnd will get in a few months: +

        + +
        primitive scope limitation +
        line layer none +
        arc layer none +
        text layer none +
        polygon layer none +
        padstack global none +
        subcircuit global none +
        +

        +This means four major changes: "subcircuits as footprints", "subcircuit +in subcircuit", "removal of elements" and "padstack instead of via". +The result is a much cleaner model consisting of less primitives that are +more universally usable. + +

        3. subcircuits as footprints

        +

        +For subcircuits to be available as footprints the new "terminal" concept +is being introduced. A terminal is not a new drawing primitive, but a property +of existing objects (made of other primitives). If an object is tagged to be +part of a terminal, it starts acting as a terminal. Copper objects of a terminal +can accept netlist connections just as pins and pads used to. A terminal has +an ID that is similar to the old "pin number", "pad number" concepts. +

        +The other important aspect is to be able to assign an ID ("refdes") to the +subcircuit. +

        +Most of these should be finished in the current development cycle and should +be released this autumn. + +

        4. subcircuits in subcircuits

        +

        +Independently of that, to remove the last piece of limitation, a subcircuit +will be able to host a subcircuit. This will enable users to build hierarchical +boards, potentially supported by hierarchical netlists. +

        +This may happen in this development cycle or in the next. + +

        5. removal of elements

        +

        +Once 3. is done, the old element model can be removed. For that, all IO +plugins need to be upgraded first; they need to: +

          +
        • convert elements to subcircuits on load +
        • convert subcircuits to elements on save +
        + +

        6. padstack instead of via

        +

        +Finally, the good old via would be replaced by padstack. A padstack +is an optional hole, and arbitrary (circle or polygon shaped) pads around +the hole. Different pads can be created per layer - including not only copper +layers but all layers, e.g. mask (cutout), paste, silk. It's likely that +non-circular holes (e.g. line segments) will be allowed, for slots. +

        +Since the hole is optional, a pad stack can represent a simple smd pad - with +its paste and mask, without limitations on the shape. +

        +Bonus: the hole doesn't need to be thru-hole, which means +blind/buried vias. +

        +This would probably happen next year. + +

        7. Bonus: extended primitives

        +

        +Once the number of the drawing primitives is cut back to 6, as a bonus +feature it will be easy to implement extended primitives from plugins. An +extended primitive: +

          +
        • contains function pointers to the plugin implementing it +
        • is created and edited on the UI the same way as its base primitive +
        • saved and loaded as the base primitive + arbitrary metadata intended for the plugin +
        • acts as a subcircuit, can create other primitives within +
        • optionally can be rendered (drawn) differently than the base primitive; the render code is in the plugin +
        +

        +For example a via stitch can be a polygon or a line with extra parameters to +specify via geometry and spacing. A polygon version can be used to plant a +matrix of vias easily; e.g. under the hot center pad of a DC/DC chip. If the +polygon is resized, the vias are recalculated. A line version would provide the +center-line for placing a row of vias, e.g. for a waveguide. As the line is +edited (e.g. endpoint moved, line length extended) the row of vias is recalculated. +

        +This would probably happen next year. Index: tags/1.2.7/doc/devlog/20170815_footprint.html =================================================================== --- tags/1.2.7/doc/devlog/20170815_footprint.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170815_footprint.html (revision 13657) @@ -0,0 +1,88 @@ + + +

        pcb-rnd devlog

        + +

        Why is it called subcircuit and not footprint?

        +

        by Igor2

        + +

        +This article tries to explain the existing PCB terminology for +elements, footprints and the new term subcircuit in +pcb-rnd. This article also reveals why new term "subcircuit" is +introduced instead of calling it "footprint2", "footprint+", "new +footprints" or "pcb-rnd footprints". + +

        +Quiting the original suggestion from Peter Stuge: +

        +I only write to ask that you consider calling subcircuits "footprint+",
        +"new footprint", "pcb-rnd footprint" or somesuch. What exactly the name
        +is is not so important, but since all future footprints will be subcircuits
        +I think it *is* important to maintain the existing terminology.
        +
        + +

        Current situation: element vs. footprint

        +

        +The good thing is that there are two terms in parallel, even in pcb. This +terminlogy is in pcb since the late 90s. +

        +On the user-level, they are called element and footprint. A footprint is +the generic implementation you store in your library, an element is a +specific instance that is on your board. You place a footprint on your +board, but as soon as you place it, it becomes an element. +

        +On the code-level, the same two things are called element and "library +entry". The actual implementation is called element everywhere. If you +grep the code (pcb-4.0.0), you will find 161 hits on footprint, mostly in +comments and user messages plus a flag called "is_footprint"; then 2686 +hits on "element". This is because the code is rather consistent about +separating the two concepts and the interaction with footprints is really +that small. +

        +It is important to note the difference between the two things, and I was +glad to find the original software did make the distinction. For example +pcb-rnd started to support more than one footprint format, but in the +memory, after you load a random footprint from the lib, the resulting +element will have only one format, the native format. This means a +footprint -> element is also a format conversion. So for pcb-rnd, when +loading from a file or lib or web, a gEDA/pcb .fp is a footprint, a kicad +module is a footprint, an eagle package is a footprint, a mentor graphics +cell is a footprint. (Yes, as you see, every single CAD package has a +different name for the same thing). +

        +The other aspect is that an element is always an instance, a copy of the +original footprint, with modifications to apply to the local situation. +For example you will always change the base coords and almost always will +change the refdes and the value. +

        +A third thing is how they are stored. In pcb a footprint is stored on +the disk, an element is stored in memory or on the disk (when the board +is saved). In pcb-rnd a footprint is on the disk, on the web or lives as +an element within another board (in whatever format, e.g. kicad or eagle). + +

        How does subcircuit affect this?

        +

        +On both the user and code level subcircuit is an element replacement. So +it doesn't affect the footprint concept at all. +

        +User level: a subcircuit that lives in your local disk library, on +edakrill or in an another board is called footprint, just like your kicad +module or eagle package is called footprint too. In this specific case the +actual implementation is a pcb-rnd subcircuit. +

        +Code level: all the code that handles subcircuit are new, written from +scratch; at the end the old element code will be removed. We are having a +few months when they run in parallel. Since all new code calls itself +"subc", it won't cause any collision with the old code that calls itself +"element" or "elem". + +

        Conclusion

        +

        +What is a footprint for pcb, is a footprint for pcb-rnd and +subcircuits are footprints and there's zero change on that side. What's an +element for pcb will be a subcricuit for pcb-rnd. Renaming that to +footprint+ or element+ would make more confusion than usign a different +name, like subcircuit. I also plan to support hierarchical pcbs, where +subcircuit will be a level of hierarchy, so that would cause more +confusion if they were called footprints. + Index: tags/1.2.7/doc/devlog/20170816_void.html =================================================================== --- tags/1.2.7/doc/devlog/20170816_void.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170816_void.html (revision 13657) @@ -0,0 +1,162 @@ + + +

        pcb-rnd devlog

        + +

        The Type/ptr1/ptr2/ptr3 construction and void *

        +

        by Igor2

        + +

        +If you ever dared to dive the code of pcb or pcb-rnd, you probably +remember a strange construct: many of the function calls take the +following arguments: + +

        +int Type, void *Ptr1, void *Ptr2, void *Ptr3
        +
        +

        +or save data in structs or local variables with the same types/names. +

        +This mail, that later will be converted to a devlog, gives an explanation +on what it is, when it happened, why I think it is a bad idea and how it +is being fixed in pcb-rnd. + +

        1. What it is

        +

        +The data model of pcb is a tree, but it is very rigid and restricted. A +line is always on a layer, a pin is always in an element. A layer and an +element is always in a buffer (e.g. board). The structure of the tree is +not just a convention: it's hardwired in every piece of the code. E.g. if +you have a line, the code knows/assumes the parent must be a layer, it +can't be anything else. +

        +Thus there is "no need for objects to remember their own type or their +place in the tree, e.g. remembering their parent". +

        +Instead all searches are done from up to down, e.g. if we are looking for +pins, we start from buffer (board) level and we are first iterating over +elements and then pins within elements. By the time we find a pin, we have +3 info at hand, in local variables: +

          +
        • the fact that the object we found is a PIN (this is going to be int +Type) + +
        • the element the pin lives in (this is going to be void *Ptr1) + +
        • the pin itself (this is going to be void *Ptr2) +
        +

        +If we are to pass the pin to the next function, we need to pass these +info, thus we pass Type, Ptr1, Ptr2 ... and Ptr3. +

        +Ptr3 is unused most of the time; when it is not unused, it's often a +"property" or child (in the tree) of Ptr2; e.g. when addressing an +endpoint of a line, Ptr2 is the line and Ptr3 refers to the endpoint. +

        +To maximize confusion, when Ptr3 is unused, it's value usually matches +Ptr2's and when only one pointer is needed (e.g. in case of an element) +all 3 pointers are the same. + +

        2. Why is it really a bad idea

        +

        +Reason #1: theoretical: one of the features C provides over e.g. asm is +types: the compiler can understand a bit more about why we do what we do. +We have a dedicated type to store the data of a pin, another for line and +a third for element. If we accidentally compare a line to a pin or we try +to say something like element = pad, because of the mismatching types, the +compiler can give a nice warning and we know we did something wrong, +without having to wait for it to bite us runtime.^1 +

        +A void * is a way to tell the compiler not to care. Since many of those +functions need to be able to handle different object types, the original +authors though it would be a good idea to tell the compiler not to care +about the object type at all. The code then looks at the "int Type" arg +and _assumes_ ptr1's and ptr2's type, knowing the rigid setup of the +tree... +

        +Reason #2: ... which makes it very very easy to introduce bugs: both the +caller and the callee need to have the very same assumptions in every +single call/function pair. Pass the wrong object in any pointer and the +software starts to misbehave in unexpected ways. There are over 40 +such type/ptr1/ptr2/ptr3 functions in pcb 4.0.0. The assumptions are not +very well documented either. +

        +Reason #3: debugging; modern debuggers like gdb are very handy: they +understand a lot of the C syntax and get enough debug info embedded in the +executable that they can explore structures and understand data types. +Unless we tell them to not do any of that, by using void *. +

        +Reason #4: the combination of the above 3: when it breaks, it's a +nightmare to figure how it broke. Some reasonable looking part of the code +starts doing something with a pin that looks broken. But tracing back +where the pin broke is often a challenge, as we never know if a given +level of function calls (stack frame) meant it to be a pin or an arc, or +thought that ptr2 is just unused while the callee expected it to be +used... +

        +Reason #5: since these assumptions about the tree are hardwired +everywhere, it's rather hard to make upgrades to the tree (like the +grouping concept subcircuits introduced in pcb-rnd, or just adding yet +another object type). It's especially too easy to miss a new +possible combination of ptr1/ptr2 in one of those many calls. For a long +time this was one of the main reasons I didn't start the data model +cleanup in pcb-rnd. +

        +Reason #6: if you have a totally valid pointer to an object you obtained +by anything else than a top-down search on the tree, you can't call the +functions, because you have no idea what Ptr1 (the parent) should be. The +workaround is: +

          +
        • either to not obtain (save, store, pass) objects without +always starting with a top-down search first + +
        • or if you ended up with an object like that, just try to repeat a +top-down search for that specific object only to figure Ptr1 +
        +

        +Needless to say, both workarounds are slow (run-time penalty) and make the +code needlessly complicated and somewhat harder to understand +(coding-time penalty). + +

        3. History: when did this happen?

        +

        +The earliest pcb version I found in pcb-history^2 that already showed +consistent use of this idiom is version 1.3. That means 1995. So this +means "we had this all the time". + + +

        4. How it is being solved in pcb-rnd

        +

        +Both in pcb and pcb-rnd there's a common header every object struct has. +It contains things like the unique ID of the object. +

        +This common header is extended in pcb-rnd so that it contains the object +type and a pointer to the object's parent object. A master-object type is +introduced, called pcb_any_obj_t - this contains only the header and can +represent any actual object. +

        +This means instead of Type/Ptr1/Ptr2, it is enough to pass a single, +self-contained pcb_any_obj_t and the callee can figure what actual object +it is and who the parent is. +

        +It's still far from true type safety^3, but at least it's much harder to +pass non-object pointers and it's impossible to pass inconsistent data +(Type or Ptr1 not matching Ptr2). It also lets the debugger and the +compiler understand what we are doing. +

        +We are in the early phase of this effort, and we are switching over the +code gradually. The first major part where Ptr1/Ptr2/Ptr3 started to +disappear is the netlist/rat (pin/pad lookup) code. + +

        Footnotes

        +

        +^1: C is not strongly typed, so this mechanism saves us from runtime bugs +only to a certain extent. However, proper use of types and const can +really catch a lot of bugs compile time. +

        +^2: http://repo.hu/projects/pcb-history/ +

        +^3: please DO NOT propose switching to C++ or sql or whatever your +favorite programming language is: pcb-rnd won't do that. If you want a +project that uses that language/tool, just fork pcb or pcb-rnd and do it. + + Index: tags/1.2.7/doc/devlog/20170924_term.html =================================================================== --- tags/1.2.7/doc/devlog/20170924_term.html (nonexistent) +++ tags/1.2.7/doc/devlog/20170924_term.html (revision 13657) @@ -0,0 +1,87 @@ + + +

        pcb-rnd devlog

        + +

        Heavy vs. light subcircuit terminals

        +

        by Igor2

        + +

        +An old element used to have only pins and pads. Both pin and pad are +very limited special cases: a pin has a single hole and the same ring around +it on every layer, a pad is just a line on either the top or bottom copper +layer (with round cap or square cap on both ends). +

        +Many of the footprint related limitations in PCB was coming from this pin/pad +model. In pcb-rnd subcircuits these limitations are removed. However, removing +limitations also means being able to make more complex things, which also +means we need to have more understanding on how we are doing things. Or at +least different understanding, not necessarily more: instead of understanding +the arbitrary limitations of pins and pads, we need to understand how arbitrary +objects may make up a terminal. + +

        Heavy terminal model

        +

        +Using arbitrary objects (of lines, arcs, polygons, texts and vias) as a terminal +is called the heavy terminal model. It is fully generic: whatever +pcb-rnd can draw can be turned into a terminal. This includes arbitrary objects +on arbitrary layers. For example an oblonged pin with two paste dots on the +top layer can be drawn as: +

        +

          +
        • a via for the pin drill +
        • a copper line one on the top copper layer, serving as the oblong pad +
        • a similar, but slightly thicker line on the top mask layer to serve as the mask cutout +
        • two short, thick lines on the top paste layer, placed on the ends of the oblong pad +
        +

        + +

        +All objects are tagged with a "term" attribute that has the same value, which +also donates the pin number. If we are after a specific pin by number, we +know all these objects are part of that. +

        +While this lets the user easily define any kind of complex terminals, it +also removes the possibility of some of our old, handy shortcuts. For example +pressing 's' on pin grew its ring diameter. But what should it do with such +a complex construct? Should it make the oblonged line thicker, but not longer? +Or grow everything proportionally? The drill diameter too, or is that an +exception? And what if it's not a drill but a slot, which is a line, should that +be grown or not? +

        +The current solution is that 's' and similar operations simply don't work on +terminals as a whole, but on individual objects of the terminals. This can +be changed later, but we won't ever have the same simple, universal 's' as we +had for pins, as we don't have the pin restrictions anymore. + +

        Light terminal model

        +

        +Later on, either in the next development cycle, or the cycle after, pad +stacks will be introduced. Pad stacks will replace vias. A pad stack is +something in between the very limited pin model and the heavy terminal model: +it offers a lot of flexibility, yet it contains some restrictions. These +restrictions will make us able to have our 's'-like operations again. +

        +A padstack will look something like this: +

          +
        • a single hole in the center, with a diameter but no ring; it's either plated or unplated (optional) +
        • an arbitrary simple-polygon shape for top copper pad (optional) +
        • an arbitrary simple-polygon shape for bottom copper pad (optional) +
        • an arbitrary simple-polygon shape for "any internal copper layer" pad (optional) +
        • an arbitrary simple-polygon shape for top mask (optional) +
        • an arbitrary simple-polygon shape for bottom mask pad (optional) +
        • an arbitrary simple-polygon shape for top paste (optional) +
        • an arbitrary simple-polygon shape for bottom paste (optional) +
        +

        +A simple-polygon is a polygon that has only one contour and no holes, can +not be cleared (i.e. lines/arcs won't make a clearance within this polygon). +

        +The light and heavy solutions will happily live side by side. I expect +vast majority of thru-hole pins and smd pads on common parts will be +specified by pad stacks. There will be a few special cases where the user +needs to use a heavy terminal; typical examples include: +

          +
        • the center pad of a qfn part that requires special paste patterns +
        • the center pad of a qfn part that requires multiple plated holes for heat dissipation +
        • oblonged pins with slots (e.g. side pin of a powerjack connector) +
        Index: tags/1.2.7/doc/devlog/20170924_term.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20170924_term.png =================================================================== --- tags/1.2.7/doc/devlog/20170924_term.png (nonexistent) +++ tags/1.2.7/doc/devlog/20170924_term.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20170924_term.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20171004_plan_mark.html =================================================================== --- tags/1.2.7/doc/devlog/20171004_plan_mark.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171004_plan_mark.html (revision 13657) @@ -0,0 +1,96 @@ + + +

        pcb-rnd devlog

        + +

        How to clean up the mark

        + +After a discussion on the mailing list, our current plan about mark handling is: + +
        +thanks for the answers, I have a better picture on how our users use the 
        +mark. Here's my proposal for the cleanup/bugfixes:
        +
        +1. we should distinguish between user placed marks and automatic marks. 
        +Whenever there's an user placed mark, only the mark related actions should 
        +remove or move the mark. In other words, if the user explicitly placed the 
        +mark, side effect of non-mark-actions shouldn't change the mark.
        +
        +2. drag&drop-like operations: for those mouse actions that start with a 
        +click then move then release, if there is no explicit user mark, the code 
        +should place the mark at click and remove it after the release.
        +
        +3. multi-click, non-drag&drop-like operations shouldn't ever change the 
        +mark. (There are too many ways such an operation can end it would be very 
        +hard to make it work like 2.)
        +
        +This means if you want to use the mark for your line length/orientation, 
        +you would need to manually place it when starting to draw the line.
        +
        +
        +
        +

        examples on how the current implementation is broken

        + +
        +The whole marker thing is a bug in itself.... Nobody understands what it is 
        +intended for and the code uses it random ways - probably developers never 
        +understood it either so each part of the code does something randomly.
        +
        +If anyone is using the mark, please let me know your use patterns. We should 
        +probably clean this up a bit, as in the current state it looks like if it did 
        +random wierd things.
        +
        +My experience of the bugs:
        +
        +The mark is sometimes placed as part of a random operation, for no appearant 
        +reason. Some operations remove the mark at the end, some cancels/undos also 
        +remove the mark. Others don't, and many operations don't place the mark. When 
        +an operation is messing with the mark, the user set mark is moved, so the user 
        +loses the original mark position. This has thaught users not to try to use the 
        +mark as it randomly jumped away.
        +
        +Examples of inconsistencies:
        +
        +1. start drawing a line; mark is placed; press esc after a few line sections, 
        +mark is removed; esc sounds like 'cancel', but it doesn't really cancel your 
        +lines, merely finishes the mode: switching to the arrow mode with F11 or the 
        +toolbar icon does the same, so it feels like the mark is only during the 
        +drawing
        +
        +2. do the same, but instead of esc, undo a few of the last lines; you go on 
        +drawing a new line from the original end of the trace where you undoed, but the 
        +mark is not moved there; so the mark doesn't mark where you last started to 
        +draw lines, but where you first started to draw lines
        +
        +3. draw a polygon: mark is placed on the start, but is _not_ removed when you 
        +finish (while in line it got removed for esc, that simply finished drawing 
        +mode); switching to arrow mode won't remove it. so it's not like in point1, 
        +marking the start during draw, but it persist
        +
        +4. now draw a polygon using the rectangle tool: no mark at all, neither during 
        +draw, nor persisting after the drawing
        +
        +5. grab a polygon point for move; while moving it, there'll be a mark at the 
        +original position; it's gone after the move - except if the operation is 
        +cancelled with esc. I'd expect exactly the opposite to happen: if it has to 
        +mess with the mark, it's more useful to see where I succesfully moved a point 
        +from than marking where I did _not_ do a change. We have undo anyway, so 
        +marking the move start doesn't make much sense either.
        +
        +6. draw arc -> no mark; start drawing lines, switch to drawing arc in the 
        +middle, the arc continues your track from the endpoint of the last line, but 
        +the mark is not removed, as if you were still in the line drawing mode... but 
        +if you started your track with arc then switched to line in the middle, the 
        +mark is placed at the end if the first line segment, which sounds totally 
        +broken
        +
        +7. placing an element won't put a mark there; moving an unselected element will 
        +move the mark to the original position; moving a selected element won't do a 
        +mark(!). This seems to be universal to all objects: moving by drag&drop marks 
        +original location, unless the object is selected
        +
        +8. drag&drop moving a line endpoint does a mark during the move, and it is left 
        +there after 'esc' but removed after a succesful move; same as in 5.
        +
        +9. ctrl+drag&drop leaves a mark at the original point for some reason, but only 
        +if mark was off before the operation
        +
        Index: tags/1.2.7/doc/devlog/20171004_plan_menu.html =================================================================== --- tags/1.2.7/doc/devlog/20171004_plan_menu.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171004_plan_menu.html (revision 13657) @@ -0,0 +1,25 @@ + + +

        pcb-rnd devlog

        + +

        How to clean up the menu system

        + +What the poll at + http://igor2.repo.hu/cgi-bin/menu-poll.cgi +suggests: + +[multikey2] The default menu file should offer two sets of hotkeys: +

        +

          +
        • multikey hotkeys (e.g. "f s" for "file, save" or "e c" for "edit, copy", similar to how it is done in gschem) +
        • single key hotkey, that always has a modifier if it is a [a..z] (e.g. ctrl+s for save, ctrl+c for copy). +
        +This would allow the transition to multi-key (pretty much unaviodable if +we want to add new functions with hotkeys) and still keep single-key items. +(Multiple hotkeys for the same menu item should work.) +

        +However, we wouldn't be able to keep single key alpha hotkeys, such as +'o' and 'f' - they will have a multi-key variant and probably a +single-key-with-modifier variant (and in return some other +single-key-with-modifier of our less often used hotkeys will lose their +single-key-with-modifier to make room for these) Index: tags/1.2.7/doc/devlog/20171019_floaters.html =================================================================== --- tags/1.2.7/doc/devlog/20171019_floaters.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171019_floaters.html (revision 13657) @@ -0,0 +1,91 @@ + + +

        pcb-rnd devlog

        + +

        subc refdes text: dyntext and floater

        +

        by Igor2

        + +the last piece of the subc "refdes text" cleanup is done. The new code +fits nicely into the new data model and pcb-rnd's approach: instead of +hardwired hacks and side effects that happen to do The Right Thing for +one specific case, provide a few, orthogonal features that can be combined +to do the same thing, or 100 other things. + +

        Old, pcb-mainline model: "element text"

        +

        +An element has 3 hardwired text objects that have to contain the refdes, +the value and the footprint name. Further limitations: +

          +
        • all three element text object have to have the same coordinates and font +and size + +
        • they can be only on silk, and all three must be on the same silk layer + +
        • special exception from under the element-lock: the only element-part +you can move without moving the element is the element text (e.g. the only +element part that can change its position compared to other parts of the +element without breaking the element up first) + +
        • and the element text can always be moved, you can't locally lock it +to the element; so you can't have a special element where the text has a +fixed position for whatever reason + +
        • there was exactly 3 of these - no more, no less + +
        • they could contain only what the programmer thought would be useful + +
        • only one of them could be displayed at a time, and which one got +displayed was a board-global setting; this global setting also affected +some +
        + +

        New, pcb-rnd subc model:

        +

        +Instead of the bunch of hardwired properites and restrictions of an +element text, subcircuits offer a set of orthogonal features that can be +used to reproduce the behavior of element texts too, but can also be used +more flexibly: +

          +
        • subcircuits consist of any object on any layer + +
        • these objects can be text, and can be on a silk layer + +
        • a text object can have the DYNTEXT flag, in which case the code does %% +substitution on the text; e.g. if the text string +contains %a.parent.refdes%, the part between the %% is substituted with +the refdes attribute ("a.") of the parent subcircuit ("parent."). In +short: it's replaced with the subcircuit's refdes + +
        • there's no limitation on the number of text objects having DYNTEXT +flags - you can have one displaying the refdes on silk, another on copper + +
        • there's no limitation on what attribute is displayed; refdes, value and +footprint name are not special any more, they are just attributes. You can +introduce your own attributes, and you can get them printed in text + +
        • with these, you can have a resistor footprint that prints both the +refdes and the value on silk, side by side + +
        • if any object of a subcircuit has the FLOATER flag, it can be moved +within the subcircuit (and can be edited without breaking up the +subcircuit); the "lock names" and "only names" became "lock floaters" and +"only floaters". +
        + +

        How to emulate the old behavior with the new features

        +

        +To get a subc refdes that behaves the same as an element refdes text, +except that it's only a refdes text and not a 3-fold "magic text": +

          +
        • on a silk layer create a text object that will be part of the subc + +
        • set the text string to %a.parent.refdes% so that it will always display +the subcircuit refdes + +
        • edit flags to turn on DYNTEXT and FLOATER; the first lets pcb-rnd +replace %% patterns, the second lets the user grab and move the text +
        +

        +Note: when you convert buffer to subc and it doesn't have a refdes text, +the code automatically adds one, so you don't need to do this manually for +each new subcircuit you draw. Index: tags/1.2.7/doc/devlog/20171103.lht =================================================================== --- tags/1.2.7/doc/devlog/20171103.lht (nonexistent) +++ tags/1.2.7/doc/devlog/20171103.lht (revision 13657) @@ -0,0 +1,389 @@ +ha:pcb-rnd-board-v3 { + + 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 = 38.1mm + 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 = 10.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:element.14626 { + x=180.0mil; y=310.0mil; + ha:attributes { + vendor_part_number=unknown + vendor=unknown + manufacturer_part_number=unknown + device=CONNECTOR_5 + manufacturer=unknown + } + + li:objects { + ha:text.14623 { + string=molex-22-23-2051-mini_5_vert.fp; x=-254.0um; y=210.0mil; scale=100; fid=0; direction=1; role=desc; + } + ha:text.14624 { + string=CONN1; x=-254.0um; y=210.0mil; scale=100; fid=0; direction=1; role=name; + } + ha:text.14625 { + string=unknown; x=-254.0um; y=210.0mil; scale=100; fid=0; direction=1; role=value; + } + ha:line.14627 { + x1=-128.0mil; y1=-6350.0um; x2=-128.0mil; y2=250.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.14628 { + x1=122.0mil; y1=-6350.0um; x2=122.0mil; y2=250.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.14629 { + x1=62.0mil; y1=-5080.0um; x2=122.0mil; y2=-5080.0um; thickness=10.0mil; clearance=0.0; + } + ha:line.14630 { + x1=62.0mil; y1=-5080.0um; x2=62.0mil; y2=200.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.14631 { + x1=62.0mil; y1=200.0mil; x2=122.0mil; y2=200.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.14632 { + x1=-128.0mil; y1=-6350.0um; x2=122.0mil; y2=-6350.0um; thickness=10.0mil; clearance=0.0; + } + ha:line.14633 { + x1=-128.0mil; y1=250.0mil; x2=122.0mil; y2=250.0mil; thickness=10.0mil; clearance=0.0; + } + ha:pin.14634 { + name=1; number=1; x=0.0; y=-5080.0um; hole=40.0mil; mask=86.0mil; thickness=80.0mil; clearance=20.0mil; + ha:flags { + pin=1 + square=1 + shape=1 + } + } + ha:pin.14635 { + name=2; number=2; x=0.0; y=-2540.0um; hole=40.0mil; mask=86.0mil; thickness=80.0mil; clearance=20.0mil; + ha:flags { + pin=1 + } + } + ha:pin.14636 { + name=3; number=3; x=0.0; y=0.0; hole=40.0mil; mask=86.0mil; thickness=80.0mil; clearance=20.0mil; + ha:flags { + pin=1 + } + } + ha:pin.14637 { + name=4; number=4; x=0.0; y=100.0mil; hole=40.0mil; mask=86.0mil; thickness=80.0mil; clearance=20.0mil; + ha:flags { + pin=1 + } + } + ha:pin.14638 { + name=5; number=5; x=0.0; y=200.0mil; hole=40.0mil; mask=86.0mil; thickness=80.0mil; clearance=20.0mil; + ha:flags { + pin=1 + } + } + } + } + ha:element.14642 { + x=180.0mil; y=800.0mil; + ha:attributes { + vendor_part_number=unknown + vendor=unknown + manufacturer_part_number=unknown + device=POLARIZED_CAPACITOR + manufacturer=unknown + } + + li:objects { + ha:text.14639 { + string={rcy(100.00mil, pol=bar-, dia=200)}; x=20.0mil; y=780.0mil; scale=100; fid=0; direction=1; role=desc; + } + ha:text.14640 { + string=C4; x=20.0mil; y=780.0mil; scale=100; fid=0; direction=1; role=name; + } + ha:text.14641 { + string=100uF; x=20.0mil; y=780.0mil; scale=100; fid=0; direction=1; role=value; + } + ha:arc.14645 { + x=0.0; y=-1270.0um; width=100.0mil; height=100.0mil; astart=90; adelta=360; thickness=10.0mil; clearance=0.0; + } + ha:pin.14643 { + name=+; number=1; x=0.0; y=0.0; hole=0.999998mm; mask=86.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + pin=1 + square=1 + } + } + ha:pin.14644 { + name=-; number=2; x=0.0; y=-2540.0um; hole=0.999998mm; mask=86.0mil; thickness=80.0mil; clearance=50.0mil; + ha:flags { + ha:thermal { component=diagonal-round; } + pin=1 + } + } + } + } + ha:rat.14646 { + x1=50.0mil; y1=60.0mil; lgrp1=3; x2=180.0mil; y2=210.0mil; lgrp2=8; + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.14618 { clearance=40.0mil; + li:geometry { + ta:contour { + { 50.0mil; 60.0mil } + { 37.592mm; 60.0mil } + { 37.592mm; 1000.0mil } + { 50.0mil; 1000.0mil } + } + } + + ha:flags { + clearpoly=1 + } + } + } + } + + ha:solder { + lid=1 + group=8 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:comp-GND { + lid=2 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:comp-power { + lid=3 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:sold-GND { + lid=4 + group=8 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:sold-power { + lid=5 + group=8 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:signal3 { + lid=6 + group=5 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:outline { + lid=7 + group=7 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:silk { + lid=8 + group=10 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + } + + ha:silk { + lid=9 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + } + } + } + + + ha:netlists { + li:input { + ha:+12V { + li:conn { C2-2; C4-1; CONN3-3; VREG1-3; } + } + ha:+15V { + li:conn { CONN1-4; R1-1; } + } + ha:-12V { + li:conn { C6-2; C8-1; CONN3-4; VREG2-3; } + } + ha:-15V { + li:conn { CONN1-3; R2-2; } + } + ha:Chassis { + li:conn { CONN1-1; CONN3-1; } + } + ha:GND { + li:conn { C1-1; C2-1; C3-2; C4-2; C5-1; C6-1; C7-2; C8-2; CONN1-2; CONN3-2; VREG1-2; VREG2-1; } + } + ha:unnamed_net1 { + li:conn { C5-2; C7-1; R2-1; VREG2-2; } + } + ha:unnamed_net2 { + li:conn { C1-2; C3-1; R1-2; VREG1-1; } + } + } + } + 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 { } + } + } + } +} Index: tags/1.2.7/doc/devlog/20171103_polyrat.html =================================================================== --- tags/1.2.7/doc/devlog/20171103_polyrat.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171103_polyrat.html (revision 13657) @@ -0,0 +1,34 @@ + + +

        pcb-rnd devlog

        + +

        unfixable polygon rat bug

        +

        by Igor2

        +

        +The following tricky polygon vs. rat bug was reported by Evan Foss, +among with the minimal test file that +reporuces it. The bug is that instead of the circular rat mark that +indicates the pin is within the poly it tries to connect to, a rat line +is drawn to a corner of the poly. +

        +After some debugging I figured this is "by design" in the polygon code +and can not be fixed. IRC log: +

        +
        when trying to check whether the point is within the polygon, it ignores holes +
        else it would never say it's within the poly, because it's always sitting in a clearance cutout hole, that's why it's not connected in the first place +
        makes sense +
        but look at your example +
        is it in a hole? +
        turn off silk +
        turn off pins/pads +
        zoom in, zoom in a lot +
        and you will find: it's not a hole, because the clearances all merged and they reached the outer contour of the poly +
        to keep the poylgon well behaved (and thus easy to process for all parts of the code!), the poly code has guarantees for a few things +
        one of the guarantees is that a hole is always fully within the polygon +
        a hole can't touch the contour +
        if the hole touches the contour, it's not a hole any more +
        instead the contour of the poly got more complex, and there are no holes +
        exactly what you see here, and your pin is sitting in the middle of an U +
        so unfortunately this is something I can not fix +
        because it's impossible to distinguish the case when we are sitting in the U because of clearance cutouts from the case when it's the polygon's shape as desribeed by the user, or by other object's clearances + Index: tags/1.2.7/doc/devlog/20171104/TODO =================================================================== --- tags/1.2.7/doc/devlog/20171104/TODO (nonexistent) +++ tags/1.2.7/doc/devlog/20171104/TODO (revision 13657) @@ -0,0 +1,4 @@ ++ thermal showcase png +- global vs. local clearance +- rendering color: far side vs. pad color +- the viaon flag should affect whether padstacks are drawn Index: tags/1.2.7/doc/devlog/20171104/thermals.lht =================================================================== --- tags/1.2.7/doc/devlog/20171104/thermals.lht (nonexistent) +++ tags/1.2.7/doc/devlog/20171104/thermals.lht (revision 13657) @@ -0,0 +1,805 @@ +ha:pcb-rnd-board-v4 { + 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 = 1.0mil + hole = 31.5mil + clearance = 12.0mil + } + } + + ha:meta { + ha:size { + thermal_scale = 0.500000 + x = 46.355mm + y = 49.53mm + isle_area_nm2 = 200000000.000000 + } + ha:cursor { + zoom = 1.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 { + ha:padstack_ref.736 { + proto = 0 + xmirror = 0 + x = 675.0mil + rot = 0.000000 + y = 800.0mil + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.737 { + proto = 0 + xmirror = 0 + x = 875.0mil + rot = 0.000000 + y = 800.0mil + li:thermal { + 13 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.738 { + proto = 0 + xmirror = 0 + x = 27.305mm + rot = 0.000000 + y = 800.0mil + li:thermal { + 9 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.739 { + proto = 0 + xmirror = 0 + x = 1.275in + rot = 0.000000 + y = 800.0mil + li:thermal { + 14 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.740 { + proto = 0 + xmirror = 0 + x = 37.465mm + rot = 0.000000 + y = 800.0mil + li:thermal { + 10 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.741 { + proto = 0 + xmirror = 0 + x = 42.545mm + rot = 0.000000 + y = 800.0mil + li:thermal { + 11 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.742 { + proto = 1 + xmirror = 0 + x = 675.0mil + rot = 0.000000 + y = 1.125in + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.743 { + proto = 1 + xmirror = 0 + x = 875.0mil + rot = 0.000000 + y = 1.125in + li:thermal { + 13 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.744 { + proto = 1 + xmirror = 0 + x = 27.305mm + rot = 0.000000 + y = 1.125in + li:thermal { + 9 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.745 { + proto = 1 + xmirror = 0 + x = 1.275in + rot = 0.000000 + y = 1.125in + li:thermal { + 14 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.746 { + proto = 1 + xmirror = 0 + x = 37.465mm + rot = 0.000000 + y = 1.125in + li:thermal { + 10 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.747 { + proto = 1 + xmirror = 0 + x = 42.545mm + rot = 0.000000 + y = 1.125in + li:thermal { + 11 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.748 { + proto = 2 + xmirror = 0 + x = 675.0mil + rot = 0.000000 + y = 37.465mm + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.749 { + proto = 2 + xmirror = 0 + x = 875.0mil + rot = 0.000000 + y = 37.465mm + li:thermal { + 13 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.750 { + proto = 2 + xmirror = 0 + x = 27.305mm + rot = 0.000000 + y = 37.465mm + li:thermal { + 9 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.751 { + proto = 2 + xmirror = 0 + x = 1.275in + rot = 0.000000 + y = 37.465mm + li:thermal { + 14 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.752 { + proto = 2 + xmirror = 0 + x = 37.465mm + rot = 0.000000 + y = 37.465mm + li:thermal { + 10 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.753 { + proto = 2 + xmirror = 0 + x = 42.545mm + rot = 0.000000 + y = 37.465mm + li:thermal { + 11 + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.754 { + proto = 0 + xmirror = 0 + x = 475.0mil + rot = 0.000000 + y = 800.0mil + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.755 { + proto = 1 + xmirror = 0 + x = 475.0mil + rot = 0.000000 + y = 1.125in + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.756 { + proto = 2 + xmirror = 0 + x = 475.0mil + rot = 0.000000 + y = 37.465mm + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 20.0mil + } + ha:padstack_ref.757 { + proto = 3 + xmirror = 0 + x = 675.0mil + rot = 0.000000 + y = 1.725in + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.758 { + proto = 3 + xmirror = 0 + x = 475.0mil + rot = 0.000000 + y = 1.725in + li:thermal { + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.759 { + proto = 3 + xmirror = 0 + x = 875.0mil + rot = 0.000000 + y = 1.725in + li:thermal { + 13 + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.760 { + proto = 3 + xmirror = 0 + x = 27.305mm + rot = 0.000000 + y = 1.725in + li:thermal { + 9 + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.761 { + proto = 3 + xmirror = 0 + x = 1.275in + rot = 0.000000 + y = 1.725in + li:thermal { + 14 + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.762 { + proto = 3 + xmirror = 0 + x = 37.465mm + rot = 0.000000 + y = 1.725in + li:thermal { + 10 + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + ha:padstack_ref.763 { + proto = 3 + xmirror = 0 + x = 42.545mm + rot = 0.000000 + y = 1.725in + li:thermal { + 11 + } + ha:flags ={ clearline=1 + }; clearance = 25.0mil + } + } + li:layers { + + ha:top-sig { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.769 { clearance=40.0mil; + li:geometry { + ta:contour { + { 550.0mil; 600.0mil } + { 45.085mm; 600.0mil } + { 45.085mm; 1.9in } + { 550.0mil; 1.9in } + } + } + + ha:flags { + clearpoly=1 + } + } + ha:text.716 { + string=plain; x=425.0mil; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.717 { + string=no thermal; x=625.0mil; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.718 { + string=round+diagonal; x=825.0mil; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.719 { + string=round+orthogonal; x=26.035mm; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.720 { + string=sharp+diagonal; x=1.225in; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.721 { + string=sharp+orthogonal; x=36.195mm; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.722 { + string=solid/connected; x=1.625in; y=550.0mil; scale=100; fid=0; direction=1; + ha:flags { + clearline=1 + } + } + ha:text.723 { + string=Line,; x=100.0mil; y=725.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.724 { + string=round cap; x=100.0mil; y=800.0mil; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.725 { + string=Line,; x=100.0mil; y=26.67mm; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.726 { + string=square cap; x=100.0mil; y=1.125in; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.727 { + string=Convex; x=100.0mil; y=1.4in; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.728 { + string=polygon; x=100.0mil; y=37.465mm; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.729 { + string=Filled; x=100.0mil; y=1.65in; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + ha:text.730 { + string=circle; x=100.0mil; y=1.725in; scale=100; fid=0; direction=0; + ha:flags { + clearline=1 + } + } + } + } + + ha:bottom-sig { + lid=1 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:top-gnd { + lid=2 + group=3 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:bottom-gnd { + lid=3 + group=10 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:int-sig2 { + lid=4 + group=7 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:int-sig1 { + lid=5 + group=5 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:outline { + lid=6 + group=9 + ha:combining { } + visible=1 + + li:objects { + } + } + + ha:bottom-silk { + lid=7 + group=12 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + } + + ha:top-silk { + lid=8 + group=1 + ha:combining { auto=1; } + visible=1 + + li:objects { + } + } + + ha:top-paste { + lid=9 + group=0 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + } + + ha:top-mask { + lid=10 + group=2 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + } + + ha:bottom-mask { + lid=11 + group=11 + ha:combining { sub=1; auto=1; } + visible=0 + + li:objects { + } + } + + ha:bottom-paste { + lid=12 + group=13 + ha:combining { auto=1; } + visible=0 + + li:objects { + } + } + } + li:padstack_prototypes { + ha:ps_proto_v4 { + htop = 0 + li:shape { + ha:ps_shape_v4 { + clearance = 50.0mil + ha:ps_line { + y2 = 62.5mil + thickness = 80.0mil + x1 = 0.0 + x2 = 0.0 + square = 0 + y1 = -1587.5um + } + ha:layer_mask { + copper = 1 + top = 1 + } + ha:combining { + } + } + } + hdia = 0.0 + hbottom = 0 + hplated = 0 + } + + ha:ps_proto_v4 { + htop = 0 + li:shape { + ha:ps_shape_v4 { + clearance = 50.0mil + ha:ps_line { + y2 = 62.5mil + thickness = 80.0mil + x1 = 0.0 + x2 = 0.0 + square = 1 + y1 = -1587.5um + } + ha:layer_mask { + copper = 1 + top = 1 + } + ha:combining { + } + } + } + hdia = 0.0 + hbottom = 0 + hplated = 0 + } + ha:ps_proto_v4 { + htop = 0 + li:shape { + ha:ps_shape_v4 { + clearance = 50.0mil + li:ps_poly { + -1270.002um + -2857.501um + -1270.002um + 2.857499mm + 1.269998mm + 2.857499mm + 1.269998mm + -1587.501um + -0.002um + -2857.501um + } + ha:layer_mask { + copper = 1 + top = 1 + } + ha:combining { + } + } + } + hdia = 0.0 + hbottom = 0 + hplated = 0 + } + ha:ps_proto_v4 { + htop = 0 + hdia = 0.0 + li:shape { + ha:ps_shape_v4 { + clearance = 50.0mil + ha:ps_circ { + dia = 80.0mil + x = 0.0 + y = 0.0 + } + ha:layer_mask { + copper = 1 + top = 1 + } + ha:combining { + } + } + } + hbottom = 0 + hplated = 0 + } + } + } + + + 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; intern=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/1.2.7/doc/devlog/20171104/thermals.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/20171104/thermals.png =================================================================== --- tags/1.2.7/doc/devlog/20171104/thermals.png (nonexistent) +++ tags/1.2.7/doc/devlog/20171104/thermals.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/20171104/thermals.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/20171104_padstack.html =================================================================== --- tags/1.2.7/doc/devlog/20171104_padstack.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171104_padstack.html (revision 13657) @@ -0,0 +1,222 @@ + + +

        pcb-rnd devlog

        + +

        Pad stacks announcement

        +

        by Igor2

        +

        + +

        Intro

        + +

        1. What is a padstack?

        +

        +A padstack is an optional hole (plated or unplated) and a list of +layertype-shape pairs for the pads. Layertype includes not only copper, +but any layer type. + +

        What can a padstack do?

        +

        +It is the replacement object for vias, pins and smd pads. It is universal +enough that it's easy to describe all three cases. It removes almost every +limitation in those objects that ever got mentioned on the mailing list. +It's so universal that it can make perfect fiducials and align markers. + +

        How does it make a PCB designer's life easier?

        +

        +It introduces the following features, which will be described in separate +announcements to keep things shorter: +

          +
        • almost arbitrary pad shapes for pins, vias and smd pads (e.g. oblong +pads, asymmetric circles or octagons, hexagons, pentagons, arbitrary +convex polygons) + +
        • different pad shape on various layers (e.g. smaller pad on inner copper +layer vs. larger pad on outer copper layer) + +
        • possibility for explicit, user defined shapes even on mask and paste +layers + +
        • blind/buried via + +
        • cache/library of matching padstacks - possibility to change one and +affect all instances, but also possibility to take out a single padstack +from the group to deviate + +
        • thermal on anything - there's no difference between smd pad or pin +
        + +

        How does it make the coder's life easier?

        + +
          +
        • a single, unified object instead of 3 different objects (via, pin, pad) + +
        • shape is not a flag anymore - no more square or octagon flag, but a +clean API that returns the actual shape on the given layer + +
        • pcb-rnd has extensive IO capability to other file formats (kicad, eagle, +hyperlinks, etc.); with padstacks it's much easier to reproduce their pads +
        + +

        Next steps, what to expect

        +

        +First, we are getting padstack related bugs and missing features fixed in +trunk/ as our users are starting to test it. Then the next release, +scheduled to the end of 2017, will feature a hopefully 100% stable, +production quality padstack support. +

        +We will then start rewriting the IO plugins to support padstacks instead +of vias, pins and pads. This includes the .pcb plugin too - it will +convert old data to padstacks on load and padstacks to old data on save, +transparently. +

        +Finally, when no code uses the old data model anymore, we will remove +a lot more code than we had to add for padstacks and subcircuits. We will +remove pads, pins, vias, elements, element lines and element arcs. This +will probably happen some time in 2018. + + +

        2. Thermals

        + +

        +A padstack normally includes shapes, one per layer type. "Normally", +because it's optional: for example the simplest mounting hole can be a +padstack that has an unplated hole and no shapes at all. The hole is +optional too: an smd pad typically contains shapes (e.g. for top copper, +top mask and top past but no hole. + +

        +A shape is a filled circle, a line (round or square cap) or an arbitrary +shaped convex polygon. The shape doesn't have to be centered at the hole. + +

        +Restrictions: only one shape per layer type, only one hole per padstack. +(This is enough for vast majority of the use cases, for the rest, heavy +terminals in subcircuits shall be used; a heavy terminal can contain +anything that can be drawn on a PCB, without restriction.) + +

        +Since an arbitrary shaped pin or via needs to be able to make a thermal, +the thermal code got upgraded to handle all the above shapes. A matrix of +how they each look: + +

        + + + + + +

        +And yes, this does mean smd pads can have thermals, as long as they are +done with the new padstacks, and not the old pad objects. + +

        +The ability to have different shape per layer type makes it easier to use +the inner layers of dense boards: outer layers can have larger pads for +better soldering of through-hole pins, while inner pads can be as small as +the fab permits, to allow more traces to pass between them. + +

        +A padstack instance can be rotated and mirrored, still referring to the +same central padstack prototype for the shapes. A padstack instance can +have a different clearance, still using the same prototype. If a padstack +instance needs to deviate, it's very cheap to copy the prototype and +starts its own group with the deviations included. + +

        +There are two features I have not decided about yet, but will do in a few +days: + +

          +
        • I have half-working code for a "thermal style" that removes the copper +shape on a specific layer group; this again could be used for saving space +on inner layers + +
        • I have half-working code for a per-shape clearance; it may be that I +will provide both a global, per pad stack instance clearance option and a +padstack prototype defined per shape clearance. Rationale: some IPC +suggests the clearance on inner layers can be tighter than on outer +layers, for various reasons. This may matter on dense boards. +
        + +

        3. blind/buried vias

        +

        +Because a padstack already has to be able to look up its pad shape on a +per layer group (physical layer) basis, it was sort of trivail to add +blind/buried vias too. +

        +The hole starting layer group and ending layer group is specified in a way +that is transferrable between different pad stacks. The simplest thing to +describe is the all-way throuh hole (needs no extra parameter). The second +simplest is a blind hole (needs one parameter). A buried hole needs 2. +

        +Following the best pcb-rnd traditions, things are not entangled: whether +a padstack has a hole or not does not depend on whether it has shapes on +copper or other layers. Whether a hole is plated does not depend on if +it's through, blind or buried. +

        +This gives the user maximum flexibility of combining the features, even +building things that we would normally regard broken constructs, like an +unplated buried hole between two inner layers, with a pad on each layer. +

        +Again following the best pcb-rnd traditions, we are not to outsmart the +user. We let the user do what the user finds useful. Later on we will +provide DRC to warn for strange looking constructs, but it's the user's +responsibility to use or abuse a feature. + +

        4. UI

        +

        +pad stacks can be created similar to elements and subcircuits: draw +objects on various layers, then select them and convert the selection to +padstack using a menu. Or select them, copy to buffer, and convert the +buffer. +

        +There will be soon a padstack breakup function too, again similar to what +elements and subcircuits have these days. And of course, some time later +there might be a way to save and load padstacks, just like footprints, and +then pcb-rnd will be able to open the padstack files directly for +editing, just like when we edit elements or subcircuits. We may even end +up having a library selection system for them, similar to the footprint +lib's. +

        +Another UI feature is a new dialog box (supported by all gtk and lesstif +HIDs!) that presents two tabs: one for the specific padstack reference the +user clicked on and one for the prototype. This dialog allows the user to +change the basic parameters, like clearance and hole properties, including +plating and bbvia aspects. +

        +Later on this dialog will offer shortcuts for copying and transforming +shapes, per layer type, e.g. it will be easy to do things like "copy top +copper shape to top mask, bloat it up by 5%". +

        +Another TODO for the near future is that the routing style should have a +padstack prototype for each style, instead of via parameters. And there +should be a very simple dialog that can create a "classic via" prototype +using only the hole diameter, ring diameter and clearance. + + +

        5. Implementation details

        +

        +A padstack put on a board is really just a reference to a padstack +prototype, sort of "copy that prototype to this x;y location, with this +rotation angle and mirror it". The prototypes are kept in a +transparent cache. +

        +Since prototypes have to be retrieved during drawing, the above process +shall be fast. It would be suboptimal to perform the rotation and +mirroring on each draw. Instead, each rotated/mirrored ("transformed") +version ever referenced are kept in the cache and are referenced directly +by the padstack reference. These tranformed variants are not saved in +files but are always generated runtime, upon the first request. If the +shape needs to be changed, e.g. bloat or shrink, all the cached tranformed +variants need to go under the same operation. +

        +The non-transformed version of each prototype is called the "canonical +form" and is saved/loaded on file IO. (Padstacks are obviously accessible +only in our native format at the moment; later on alien formats that also +support some sort of pad stacks will catch up; we are not going to change +the .pcb format, tho, so padstacks will not be available there) +

        +A low level of the padstack code uses a hash algorithm for being able to +rapidly detect if the canonical variant of a prototype to be added already +presents in the cache - if so the, duplicate is not added, but the +existing item is referenced. Index: tags/1.2.7/doc/devlog/20171117_chgstat.html =================================================================== --- tags/1.2.7/doc/devlog/20171117_chgstat.html (nonexistent) +++ tags/1.2.7/doc/devlog/20171117_chgstat.html (revision 13657) @@ -0,0 +1,120 @@ + + +

        pcb-rnd devlog

        + +

        Code change statistics

        +

        by Igor2

        + +

        1. About

        +

        +The code change statistics is an attempt to measure how much of the +code base has been changed since the fork. It is calculated by a script, +using svn metadata. +

        +Code change has many aspects. The other day an user asked me to list +what's new/different/more in pcb-rnd compared to pcb mainline and I realized +we have so many new things that a complete list would be so long nobody +bothered to read. +

        +It is possible to have a few features highlighted, but the selection is +subjective. For example what took much time is the data model rewrite, which +led to removing all layer and footprint limitations and an unified padstack model. +This costed many many hundred hours of developer time. On the other hand, many +of users love fp_wget, which transparently integrates edakrill and gedasymbols +in the library window - that feature literally costed 2 weekends, total. +

        +The code change statistics is just one aspect, an objective one. But +interpretation of the method and the result is obviously subjective. My +interpretaton is that it shows how many lines of pcb-rnd code does not +look similar to its corresponding mainline code line. This means code +lines that got major change or code lines that are new in pcb-rnd and +never existed in mainline. + +

        2. Technical details: how it is calculated

        +

        +The chgstat script runs svn blame on all source files to get each source +line prefixed by the svn revision number when it last changed. The main +idea is that if a line changed after the fork, it's new, if it's part of +the original import, it's old. At the end the percentage is derived from +new/(old+new). +

        +The fine print: we mask out a lot of changes. For example if a file gets +split into two files or a file gets renamed, code gets moved within a +file, or code gets reindented, we tell chgstat to take that revision as +old. +

        +This method is not perfect. The most trivial shortcomings are: +

          +
        • If there is a real change in r100 then an indentation change in r200, + we have to tell chgstat to account r200 changes to the old code; this + masks the new lines of r100, counting them as old too. +
        • The script works on physical source lines - including empty lines and + even the license banners. These lines rarely change, so even if + we changed all actual code of the original source, we still wouldn't + see 100% in the statistics because of the unchanged empty lines and + license banners +
        • On the other hand, when a new source file is added, it contains the + license banner and empty lines, and these are counted as new code + lines too (this probably justifies the previous loss) +
        • Some changes, like namespace cleanup (massive renames), are hard to categorize; when done + right, they don't change how pcb-rnd works but they make the code look + different. Because of how the change statistics is defined, and how + much actual work a good quality rename requires and how it improves the + code base, we count these as change. +
        +We follow a rather conservative policy: when we are in doubt, we rather +classify the revision as 'old'. This, combined with the masking effect suggests +that errors of the method favor 'old'. In other words, the result is a +lower estimate of the actual change. +

        +So what does 1% mean? Our current codebase (as of November 2017) is about +230k lines, so 1% means about 2300 lines of code. + +

        3. Why do we have this stats?

        +

        +The only reason is to have anything that's remotely objective. I started +to do this stat at around 25%. Back then the code modularization and namespace +cleanup contributed the most. It was fun to see how the number rised by adding +new I/O plugins and rewriting the data model. +

        +It also somewhat shows the sheer amount of low level codecraft that takes +place under each high level feature addition or infrastructure refactoring. +It shows that doing the huge changes in pcb-rnd are not only theoretical; it's +not only about thinking things over, designing mechanism, but it's also about +a lot of typing. +

        +But it's important to handle this statistics at its right place, and don't +overestimate it's importance. What makes pcb-rnd so good is not how many lines +of code we put in, but what the code does and how much effort we invest. + +

        4. Fork vs. rewrite

        +

        +At any time you are reading this article, we have a rather high code change +percentage. At the moment of writing the article, it's over 65%. Users +somtime ask: "so if we/you changed more than half/two-third/three-quarter of +the code, wouldn't it have been easier to just rewrite it from sratch?". The +short answer is clearly no, fork was the better way. The longer answer +is: +

        +

          +
        • Even tho a lot of code has changed, some essential code remained. Some + infrastructure or low level code was just right, and I am glad I + did not have to rewrite those parts. +
        • In a sense, pcb already did mostly what we needed, so taking it and + making the modifications was cheaper than starting from scratch. Remember: + code change stat includes everything from small changes to new code. +
        • Unlike git people, we have a different development model. Instead of + working for 2 years in isoaltion and then presenting the results, we + are working in public. Additions of the code, redesign of critical + infrastrucutre, changing the data model all goes on the live version - + there are no branches. (This forces developers to be a bit more + careful about how specific changes are carried out, but this pays + back many times ni early user testing.) This method requires a + software that is already there, already works. That's not cheap + to get if we write it from scratch. +
        +

        +With cschem we take a different +approach and write it from scratch. The reason is that gschem/gnetlist/lepton +is not very close to what we want to get at the end. The differences are +large, both on design level and on actual code level. Index: tags/1.2.7/doc/devlog/_template =================================================================== --- tags/1.2.7/doc/devlog/_template (nonexistent) +++ tags/1.2.7/doc/devlog/_template (revision 13657) @@ -0,0 +1,18 @@ + + +

        pcb-rnd devlog

        + +

        [TODO: title of the article]

        +

        by [TODO: author]

        + +

        [TODO: section]

        +

        +para +

        +para + +

        [TODO: section]

        +

        +para +

        +para Index: tags/1.2.7/doc/devlog/poll_common/gencsv.sh =================================================================== --- tags/1.2.7/doc/devlog/poll_common/gencsv.sh (nonexistent) +++ tags/1.2.7/doc/devlog/poll_common/gencsv.sh (revision 13657) @@ -0,0 +1,3 @@ +#!/bin/sh +sed "s@\t@,@g" < poll.tsv > poll.csv +tr "\n" "," < header > header.csv Property changes on: tags/1.2.7/doc/devlog/poll_common/gencsv.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/devlog/poll_common/genhtml.sh =================================================================== --- tags/1.2.7/doc/devlog/poll_common/genhtml.sh (nonexistent) +++ tags/1.2.7/doc/devlog/poll_common/genhtml.sh (revision 13657) @@ -0,0 +1,54 @@ +#!/bin/sh +( +echo '' +echo "" +sed "s@^@" +hl=`wc -l < header` +for n in `seq $hl` +do + ./genpie.sh $n + fn=pie_col_$n.png + if test -f "$fn" + then + echo "
        @" < header +sed "s@^@
        @;s@\t@@g" < poll.tsv +echo "
        " + else + echo " " + fi +done + +echo '
        ' +if test -f "legend.txt" +then + echo "

        " + echo "

        Legend

        " + echo "
        "
        +	cat legend.txt
        +	echo "
        " +fi + +echo "

        Downloads

        " +echo '
          ' + +if test -f poll.csv +then + echo '
        • csv data | csv header ' +fi + +if test -f poll.tsv +then + echo '
        • tsv data (raw, no header)' +fi + +if test -f legend.txt +then + echo '
        • legend ' +fi + +echo '
            ' + +echo '' +) > poll.html + + Property changes on: tags/1.2.7/doc/devlog/poll_common/genhtml.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/devlog/poll_common/genpie.sh =================================================================== --- tags/1.2.7/doc/devlog/poll_common/genpie.sh (nonexistent) +++ tags/1.2.7/doc/devlog/poll_common/genpie.sh (revision 13657) @@ -0,0 +1,38 @@ +#!/bin/sh + +gen() +{ + awk -F "[\t]" -v "col=$1" ' + BEGIN { + if (col < 0) { + col = -col + keep_na = 1 + } + } + { + val=$col + if (val == "-") { + if (keep_na) + val="n/a" + else + next + } + split(val, VAL, "[+]") + for(n in VAL) { + VOTE[VAL[n]]++ + } + } + + END { + for(n in VOTE) { + print "@slice\n" VOTE[n] + print "@label\n" n + } + } + ' +} + +for n in $* +do + (gen $n < poll.tsv | animpie && echo "screenshot \"pie_col_$n.png\"") | animator -H -x 150 -y 150 +done Property changes on: tags/1.2.7/doc/devlog/poll_common/genpie.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_annot.dot =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_annot.dot (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_annot.dot (revision 13657) @@ -0,0 +1,19 @@ +digraph annot { + + + gnetlist [shape=box] + + {rank=same pcb gschem spacer1} + + spacer1 [style=invisible] + + foo [shape=box] + + gschem -> gnetlist [label="forward1"] + pcb -> foo [label="back1"] + + gschem->spacer1->pcb [style=invisible arrowhead=none] + + gnetlist -> pcb [label="forward2"] + foo -> gschem [label="back2"] +} Index: tags/1.2.7/doc/devlog/res/20150830b_annot.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_annot.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_annot.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_annot.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_annot.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s0.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s0.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s0.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s0.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s0.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s1.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s1.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s1.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s2.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s2.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s2.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s3.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s3.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s3.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s4.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s4.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s4.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s4.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s4.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s5.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s5.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s5.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s5.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s5.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/20150830b_s6.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/devlog/res/20150830b_s6.png =================================================================== --- tags/1.2.7/doc/devlog/res/20150830b_s6.png (nonexistent) +++ tags/1.2.7/doc/devlog/res/20150830b_s6.png (revision 13657) Property changes on: tags/1.2.7/doc/devlog/res/20150830b_s6.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/devlog/res/Makefile =================================================================== --- tags/1.2.7/doc/devlog/res/Makefile (nonexistent) +++ tags/1.2.7/doc/devlog/res/Makefile (revision 13657) @@ -0,0 +1,4 @@ +all: 20150830b_annot.png + +%.png: %.dot + dot -Tpng < $^ > $@ Index: tags/1.2.7/doc/doc.html =================================================================== --- tags/1.2.7/doc/doc.html (nonexistent) +++ tags/1.2.7/doc/doc.html (revision 13657) @@ -0,0 +1,37 @@ + + + + pcb-rnd - news + + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +
            + +

            pcb-rnd documentation

            + + + + + Index: tags/1.2.7/doc/features/debian.html =================================================================== --- tags/1.2.7/doc/features/debian.html (nonexistent) +++ tags/1.2.7/doc/features/debian.html (revision 13657) @@ -0,0 +1,67 @@ + + + + pcb-rnd - [debian] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [debian] patch

            + +Our new goal is to get official Debian packages in Debian testing. The old, +home grown packaging is already removed to ease the official packaging, but +the official packages are not yet available. Please be patient. +

            +The previous, obsolete packaging was: +

            + +Our current Debian packaging reflects the modularity of pcb-rnd: it has +most plugins in separate packages. The main package is called +pcb-rnd-core: this provides the executable and the footprint library +and the batch HID. The GUI HIDs are in pcb-rnd-gtk and +pcb-rnd-lesstif - it's possible to install neither, either or both. +When there are multiple HIDs installed, the user can select one by the +--gui command line parameter or by changing the GUI preference in the +configuration (the default preference is gtk > lesstif > batch). + +

            + +The rest of the packages are features, importers and exporters, e.g. +pcb-rnd-svg is the SVG exporter, pcb-rnd-query is the object +query language needed for the advanced search. + +

            + +A metapackage called pcb-rnd is provided for convenience: it installs +the packages for the most common, yet small setup, with the GTK HID. + +

            + +How to get the packages: + +

              +
            • decide which packages you need; this package list may help +
            • use apt-get install after configuring repo.hu's debian repository as source in your /etc/apt/sources.list +
            • use dpkg -i after manually downloading the packages from repo.hu's flat package list or from the package pool +
            • build them on your Debian box: use svn trunk, install debhelper and all the build dependencies of pcb-rnd and run "fakeroot debian/rules binary" in trunk (shorthand: "make deb") +
            + +

            plans

            +No plans - this feature is fully implemented. + + Index: tags/1.2.7/doc/features/debian_list.html =================================================================== --- tags/1.2.7/doc/features/debian_list.html (nonexistent) +++ tags/1.2.7/doc/features/debian_list.html (revision 13657) @@ -0,0 +1,68 @@ + + + + + + pcb-rnd - Debian package list + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - Debian package list

            + +
            name internal dependencies description + +
            pcb-rnd pcb-rnd-core, pcb-rnd-gtk, pcb-rnd-gerber, pcb-rnd-lpr, pcb-rnd-png, pcb-rnd-propedit, pcb-rnd-query, pcb-rnd-report, pcb-rnd-svg, pcb-rnd-xy pcb-rnd is load/save compatible with gEDA/PCB and kicad and offers various auxiliary import/export formats.

            This metapackage installs the core and the most commonly used set of plugins. +

            pcb-rnd-core This package contains the core program. Most functionality, including the GUI frontend, is in the corresponding plugin package. +
            pcb-rnd-gtk pcb-rnd-core This package contains the GTK+ user-interface for pcb-rnd. +
            pcb-rnd-lesstif pcb-rnd-core This package contains the Lesstif/Motif user-interface for pcb-rnd. +
            pcb-rnd-autocrop pcb-rnd-core This package provides the autocrop feature that can resize the board to minimum around all the existing objects. +
            pcb-rnd-autoplace pcb-rnd-core This package provides the autoplace feature used to place elements automatically and offers two different algorithms to do so. +
            pcb-rnd-autoroute pcb-rnd-core This package provides the classic gEDA/pcb autorouter. +
            pcb-rnd-diag pcb-rnd-core This package provides actions for debugging/diagnostic purposes. This feature may be needed for reporting bugs. +
            pcb-rnd-distalign pcb-rnd-core This package provides actions for arranging elements in an array. +
            pcb-rnd-distaligntext pcb-rnd-core This package provides actions for arranging text objects in an array. +
            pcb-rnd-djopt pcb-rnd-core This package provides actions to clean up (optimize) tracks. It is especially useful after autorouting. +
            pcb-rnd-gcode pcb-rnd-core This package allows exporting the design to gcode, useful for CNC milling. +
            pcb-rnd-gerber pcb-rnd-core This package allows exporting the design to gerber, accepted by most PCB fab houses. +
            pcb-rnd-lpr pcb-rnd-core This package allows printing directly from the GUI, using lpr. +
            pcb-rnd-nelma pcb-rnd-core This package allows exporting the design to nelma, for numerical capacitance calculation (via external tool) +
            pcb-rnd-png pcb-rnd-core This package allows exporting the design in various bitmap formats, including png and jpeg. +
            pcb-rnd-svg pcb-rnd-core This package allows exporting the design in SVG, the Scalable Vector Graphics format. It is useful for publishing the design on the web. +
            pcb-rnd-xy pcb-rnd-core This package allows exporting the design in XY, suitable for pick∧place machines. +
            pcb-rnd-fontmode pcb-rnd-core This package lets the user to turn the GUI into a PCB font editor. +
            pcb-rnd-fp-wget pcb-rnd-core This package provides a wget based footprint accessor, which allows integrating web directories of footprints in the library. The only currently supported site is gedasymbols.org. +
            pcb-rnd-edif pcb-rnd-core This package allows pcb-rnd to import netlists in the EDIF format. +
            pcb-rnd-mincut pcb-rnd-core This package upgrades the indication of short circuits: instead of highlighting two random pins/pads, it tries to determine the minimal-cut that would resolve the short. In practice this means it makes a suggestion where to cut the networks to remove the short circuit. +
            pcb-rnd-oldactions pcb-rnd-core This package provides some old user actions. These are not used daily anymore, but some old actions scripts may still depend on them. +
            pcb-rnd-polycombine pcb-rnd-core This package provides actions to combine (merge) multiple polygons into a single, more complex polygon. +
            pcb-rnd-propedit pcb-rnd-core This package provides the property editor function for the GUI. The property editor collects all properties and attributes of all selected objects in a table and allows the user to change them. +
            pcb-rnd-puller pcb-rnd-core This package provides actions to "pull" tracks, minimizing their length. +
            pcb-rnd-query pcb-rnd-core This package provides the query language used in the advanced search on the GUI. +
            pcb-rnd-renumber pcb-rnd-core This package provides various actions to automatically renumber elements on the design. These actions change the refdes of some (or all) elements. +
            pcb-rnd-report pcb-rnd-core This package used to provide the report action that displays basic information about design objects. Unlike propedit, report does not allow the user to manipulate any of the data reported.

            At the moment report is compiled into the core, this package is kept for compatibility and placeholder. +

            pcb-rnd-shand-cmd pcb-rnd-core This package provides 1..2 character long shorthands for the most commonly used core commands. +
            pcb-rnd-smartdisperse pcb-rnd-core This package implements a smart algorithm to disperse elements. It is useful after importing a new design from the schematics. It is an alternative to autoplace. +
            pcb-rnd-stroke pcb-rnd-core, pcb-rnd-gtk This package implements mouse gestures using libstroke. +
            pcb-rnd-teardrops pcb-rnd-core This package embeds each pin in a teardrop drawn from multiple arcs. May be useful for toner-transfer boards. +
            pcb-rnd-vendordrill pcb-rnd-core This package provides vendor drill mapping and vendor specific design rule application. +
            pcb-rnd-kicad pcb-rnd-core This package allows pcb-rnd to load and save in kicad's s-expression based (new) file format. +
            pcb-rnd-gsch2pcb This package provides the external tool gsch2pcb-rnd that can convert a gschem schematics to files that can be imported in pcb-rnd. + +
            + Index: tags/1.2.7/doc/features/dynstyle.html =================================================================== --- tags/1.2.7/doc/features/dynstyle.html (nonexistent) +++ tags/1.2.7/doc/features/dynstyle.html (revision 13657) @@ -0,0 +1,41 @@ + + + + pcb-rnd - [dynstyle] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [dynstyle] patch

            + +Pcb-rnd doesn't have a hardwired limit on number of routing styles +anymore. Routing styles can be created on the fly and are saved to and loaded +from .pcb files. +

            +There's no theoretical maximum explicitly set either. An implicit maximum +exists and is sizeof(int) - should be at least 2^31 on most systems. + +

            save/load and compatibility

            +The first 4 styles are loaded and preserved by mainline. Styles above +4 would probably be deleted in a mainline load-save cycle. The number 4 +is a constant value that can be changed if mainline is recompiled. + +

            plans

            +GUI HID representation of styles (especially in menus) need more testing. + + Index: tags/1.2.7/doc/features/flagcomp.html =================================================================== --- tags/1.2.7/doc/features/flagcomp.html (nonexistent) +++ tags/1.2.7/doc/features/flagcomp.html (revision 13657) @@ -0,0 +1,44 @@ + + + + pcb-rnd - [flagcomp] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [flagcomp] patch

            + +Many of the patches in this fork, and in possible future branches/forks +may introduce new pin, pad or element flags. PCB loads and saves flags +by converting the text representation to an in-memory binary format. Any +flag not understood is lost. +

            +This patch adds a linked list of string flags, filled in with the unknown +flags while loading a PCB. On save, these flags are appended to the normal +flag list. This preserves all unknown flags (but not order of flags) in +a load/save cycle. + +

            save/load and compatibility

            +This patch ensures compatibility in save/load cycles with flags introduced +by later versions of mainline PCB or different branches/forks of PCB by +not removing flags they introduced. + +

            plans

            +No plans - this feature is fully implemented. + + Index: tags/1.2.7/doc/features/gpmi.html =================================================================== --- tags/1.2.7/doc/features/gpmi.html (nonexistent) +++ tags/1.2.7/doc/features/gpmi.html (revision 13657) @@ -0,0 +1,61 @@ + + + + pcb-rnd - [gpmi] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [gpmi] patch

            + +Thanks to gpmi, pcb-rnd is scriptable in about 10 scripting languages (e.g. +lua, awk, ruby, python, scheme, tcl). Scripts are integrated in pcb-rnd and +have access to most of the internals. Scripts +are able to: +
              +
            • register new actions +
            • create new menus and submenus +
            • execute existing actions +
            • pop up simple dialog boxes (message, report, progress bar, file selection) -- check out the video +
            • build and pop up custom dialog boxes (so called attribute dialogs) +
            • search for objects (lines, arc, polys, vias, etc.) on the layout +
            • change and move existing objects on the layout +
            • create new objects on the layout +
            • change "page" properties (dimensions of the board) +
            • debug draw on the gui (slightly broken on gtk due to some gtk hid bugs) +
            +

            +This feature has three options: +

              +
            • disabled: not compiled at all - when gpmi is not installed (no gpmi scripting in PCB) +
            • buildin: compiled and linked in the executable - pcb-rnd always can load and run scripts +
            • plugin: compiled as a loadable plugin - pcb-rnd can load and run scripts if the plugin is installed +
            + +

            Example

            +Check out the Rosetta stone of +pcb-rnd. + +

            save/load and compatibility

            +Save/load files are not affected. + +

            plans

            +Expose more internals, write more example scripts and documentation. + + + Index: tags/1.2.7/doc/features/index.html =================================================================== --- tags/1.2.7/doc/features/index.html (nonexistent) +++ tags/1.2.7/doc/features/index.html (revision 13657) @@ -0,0 +1,51 @@ + + + + pcb-rnd - features + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd

            +

            Change summary, per topic

            + +
            commit message tag and docdescription +
            [gpmi] scripting PCB (including GUI dialogs, actions, menus, changing the layout) +
            [intconn] component internal connections +
            [nonetlist] components that are not part of the netlist and should not cause shorts +
            [tostyle] actions, menu and hotkey to change ring dia, line width, drill dia and clearance sizes to match the values defined for the current routing style +
            [square] change square pad to a generic shaped-pin based on the octagon pin code - this is an alternative to teardrops +
            [flagcomp] unknown flag compatibility +
            [scconfig] use scconfig instead of autotools +
            [res] replace resource files with lihata and enable multi-key hotkeys in both gtk and lesstif hids +
            [debian] Debian packaging the binaries configured to my own taste +
            [mods] modularize the code to reduce core size - for comparison +
            [unglib] remove glib dependency from core +
            [io_*] .pcb and .fp file format plugins +
            [dynstyle] dynamic routing style: support more than 4 of them - with no limit +
            [conf] new, unified, config file system +
            [query] query language +
            routing styles routing style fixes +
            (settings) minor changes in default settings + + + +
            + + + Index: tags/1.2.7/doc/features/intconn.html =================================================================== --- tags/1.2.7/doc/features/intconn.html (nonexistent) +++ tags/1.2.7/doc/features/intconn.html (revision 13657) @@ -0,0 +1,93 @@ + + + + pcb-rnd - [intconn] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [intconn] patch

            + +There are parts with internal connections (e.g. pin 2 and 4 of a SO8 +package are internally connected). Mainline PCB can not handle this, +leaving the following options: +
              +
            • connect both pins to the net from the schematics - this works if all the internally connected pins are required to connect to copper (common with GND or power pins) but is very inconvenient for signal pins where only one of them needs to be connected +
            • back-annotate which pin is connected - there's no easy back annotation +
            • one pin connected, the other is closer to the next target; PCB doesn't understand that they are already connected internally; normally one shouldn't use the internal connection of a component instead of copper; except for the common practice to use 0 ohm SMD resistors for jumping wires +
            +

            +The patch introduces a new pin flag intconn(g) which marks the pin +to have internal connections in group g. If there +are multiple pins using the same g value within a single element, they +are internally connected. In other words, g is a group (or net name) +within the element and pins can join to one of the numbered groups (or internal +nets). The value of g shall be between 1 and 255, 0 means no internal +connection (equivalent to the case when intconn(0) is omitted). +

            +When pin numbers are displayed (key 'd'), internal connection groups are +written in square brackets, e.g. "2 [9]" means "pin 2, internally connected +to group 9". +

            +Combined with the [nonetlist] patch, this +solves the "0-ohm 1206 jumper" problem: the element should be marked +as nonetlist, with both pins set intconn(1) - this will result in a 2 +pad element, pads internally connected, that can be part of any one network +without causing short. +

            Example

            +The first image depicts crossing traces, a common problem encountered when rats +nesting a new layout from a netlist. One method to resolve such issues is to +use a zero ohm jumper resistor that allows one signal trace to 'jump' across +another. +

            +The second image shows the layout routing the nonconflicting rats and a open +unrouted point where the rat would require one trace to cross another. +

            +In the third image a 1206 SMD footprint for a 0 Ohm 1206 resistor called J1 is +placed with an intconn between the two pads which resolves the final rat line. +

            +[Layout with resistors and rat lines] +

            +[Layout with one remaining rat line] +

            +[Layout with jumper completing net] +

            + + + +

            save/load and compatibility

            +This patch introduces a new pin flag. In the following example +pin 2 and 4 are connected internally as group 9, while pin 3 +does not have any internal connections: +
            +Pin[40000 60000 6000 3000 6600 2800 "2" "2" "square,intconn(9)"]
            +Pin[40000 50000 6000 3000 6600 2800 "3" "3" "square"]
            +Pin[40000 40000 6000 3000 6600 2800 "4" "4" "square,intconn(9)"]
            +
            +Mainline PCB will load the design ignoring internal connections - +this may introduce new rats. +

            +Mainline PCB doesn't save intconn() and elements are embedded in the file - +once the design is loaded and saved with mainline PCB, internal connection +info is lost. + +

            plans

            +No plans - this feature is fully implemented. There is no plan for implementing +a GUI, internal connections should be hand-edited into the element. + + Index: tags/1.2.7/doc/features/intconn1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/features/intconn1.png =================================================================== --- tags/1.2.7/doc/features/intconn1.png (nonexistent) +++ tags/1.2.7/doc/features/intconn1.png (revision 13657) Property changes on: tags/1.2.7/doc/features/intconn1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/features/intconn2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/features/intconn2.png =================================================================== --- tags/1.2.7/doc/features/intconn2.png (nonexistent) +++ tags/1.2.7/doc/features/intconn2.png (revision 13657) Property changes on: tags/1.2.7/doc/features/intconn2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/features/intconn3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/features/intconn3.png =================================================================== --- tags/1.2.7/doc/features/intconn3.png (nonexistent) +++ tags/1.2.7/doc/features/intconn3.png (revision 13657) Property changes on: tags/1.2.7/doc/features/intconn3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/features/io.html =================================================================== --- tags/1.2.7/doc/features/io.html (nonexistent) +++ tags/1.2.7/doc/features/io.html (revision 13657) @@ -0,0 +1,44 @@ + + + + pcb-rnd - [io_*] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [io_*] patches

            + +Mainline PCB core was coupled with the file format; the [io] patch set is +an effort to decouple any file design I/O from core. The original file format +(plain text .pcb and .fp) lives on as plugin called io_pcb. + +

            +TODO + +

            save/load and compatibility

            +Not affected when io_pcb is used and .pcb or .fp files are loaded or saved. +

            +Using other io_* implementations will obviously result in files that are +incompatible with mainline pcb (unless mainline pcb learns how to load those +formats). + +

            plans

            +The project is still in an early phase. + + + Index: tags/1.2.7/doc/features/jumper_1206.fp =================================================================== --- tags/1.2.7/doc/features/jumper_1206.fp (nonexistent) +++ tags/1.2.7/doc/features/jumper_1206.fp (revision 13657) @@ -0,0 +1,7 @@ +Element["nonetlist" "1206 jumper, 0 ohm" "" "1206" 0 0 -3150 -3150 0 100 ""] +( + Pad[-5905 -1181 -5905 1181 5118 2000 5718 "1" "1" "square,intconn(1)"] + Pad[5905 -1181 5905 1181 5118 2000 5718 "2" "2" "square,intconn(1)"] + ElementLine[-2362 -3740 2362 -3740 800] + ElementLine[-2362 3740 2362 3740 800] +) Index: tags/1.2.7/doc/features/nonetlist.html =================================================================== --- tags/1.2.7/doc/features/nonetlist.html (nonexistent) +++ tags/1.2.7/doc/features/nonetlist.html (revision 13657) @@ -0,0 +1,74 @@ + + + + pcb-rnd - [nonetlist] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [nonetlist] patch

            + +The [nonetlist] patch adds an element flag that makes PCB ignore the marked +element when dealing with netlists. This means connecting a net to a pin of +a nonetlist element will not cause a short. The refdes of a nonetlist +part is drawn with color element-color-nonetlist (ElementColor_nonetlist +in the source; default value #777777, grey). +

            +Uses of the nonetlist feature: +

              +
            • smd jumper: Combined with the [intconn] patch, this + solves the "0-ohm 1206 jumper" problem: the element should be marked + as nonetlist, with both pins set intconn(1) - this will result in a 2 + pad element, pads internally connected, that can be part of any one network + without causing short and passing the DRC. +
            • mechanical parts that should not show up on the schematics: +
                +
              • mounting hole elements: single pin holes with silk marking the head of the screw +
              • chassis (often with mounting holes or keep-out areas) +
              • logos in footprints (no poly support in footprint - yet?) +
              • mechanical parts which do not have solderable pins (plastic spacers, extra connector shields) +
              • "spare connectors", e.g. unused/disconnected DIP sockets, pin grids, or connectors in the corner of the PCB for prototyping (dev-board style) +
              +
            +

            +Preservation: gsch2pcb-rnd leaves nonetlist elements in the PCB. +

            save/load and compatibility

            +This patch introduces a new element flag. The following example demonstrates +a 1206 jumper footprint: +
            +Element["nonetlist" "1206 jumper, 0 ohm" "" "1206" 0 0 -3150 -3150 0 100 ""]
            +(
            +	Pad[-5905 -1181 -5905 1181 5118 2000 5718 "1" "1" "square,intconn(1)"]
            +	Pad[5905 -1181 5905 1181 5118 2000 5718 "2" "2" "square,intconn(1)"]
            +	ElementLine[-2362 -3740 2362 -3740 800]
            +	ElementLine[-2362 3740 2362 3740 800]
            +)
            +
            +Mainline PCB will load the design ignoring internal connections and nonetlist +flag - this will cause shorts on all connected pins/pads and will break +the connection. +

            +Mainline PCB doesn't save nonetlist and elements are embedded in the file - +once the design is loaded and saved with mainline PCB, the flag is lost. +After reloading the file in pcb-rnd, the element causes the same shorts +as in mainline PCB. + +

            plans

            +No plans, the feature is complete. + + Index: tags/1.2.7/doc/features/polygrid.html =================================================================== --- tags/1.2.7/doc/features/polygrid.html (nonexistent) +++ tags/1.2.7/doc/features/polygrid.html (revision 13657) @@ -0,0 +1,38 @@ + + + + pcb-rnd - [polygrid] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [polygrid] patch

            + +Polygrid adds an option to the ps exporter to fill polygons with a grid +of horizontal and vertical lines instead of full fill. When toner transfer +is used or test prints are produced, the grid may save some toner. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Fix bugs. +

            +No (feature) plans - this feature is fully implemented. + + Index: tags/1.2.7/doc/features/query.html =================================================================== --- tags/1.2.7/doc/features/query.html (nonexistent) +++ tags/1.2.7/doc/features/query.html (revision 13657) @@ -0,0 +1,45 @@ + + + + pcb-rnd - [query] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - [query]

            +Pcb-rnd features a flexible query language that can list (or select or find, etc.) +objects matching an expression. The language handles different data types, +including lists, provides means to iterate over objects and lists, supports +the common logical and arithmetic operators. +

            +The query language is the engine behind the advanced search & select +functionality. It is also the foundation of the programmable DRC. +

            +The query language is implemented as a core plugin. +

            +TODO: more details will come later, when the specification and implementation +stabilizes. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Next stage will be a programmable DRC. + + + Index: tags/1.2.7/doc/features/res.html =================================================================== --- tags/1.2.7/doc/features/res.html (nonexistent) +++ tags/1.2.7/doc/features/res.html (revision 13657) @@ -0,0 +1,150 @@ + + + + pcb-rnd - [res] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [res] patch

            + +PCB used to have an own file format for describing resources (menu structure +and hotkey bindings, vendor drill mapping). The resource format was generic +enough to describe these things, but the syntax was somewhat weird: mixed +positional and named fields. More precisely, composite nodes could contain +named and anonymous subnodes, and the meaning of anonymous subnodes depended +on their position in the anon-subnode-list. +

            +The code that dealt with the in-memory representation of the resource tree +was weird and big chunks duplicated in the HIDs and vendor drill module. It +was also hard to parse a resource file with external tools. +

            +Since version 1.0.10, pcb-rnd replaces resource files with +lihata. Lihata is a small, generic +purpose container format that can describe arbitrary trees. Just like resource +file syntax, lihata is optimized for hand-editing: no need to use excess +quoting or long boilerplate blocks. +

            +Liblihata also provides a lot of helper functions that made the code +dealing with the menus and vendor drill resources much simpler and less +redundant. Since the parser is small and external, and since there are +external converter tools available, it is also easier to deal with the +files outside of the pcb executable. + +

            menu files

            +There are pcb-menu-gtk.lht and pcb-menu-lesstif.lht. They are in trunk/src +in the source tree and are installed in the SHAREDIR. Currently each GUI +HID (lesstif, gtk) loads the corresponding menu file. + +

            menu resource lihata structure

            +The root of a menu resource file should be a ha: with the following +children: +
              +
            • li:mouse for mouse button bindings +
            • li:main_menu for describing the main menu +
            • li:popups for describing the popup menus +
            +All children are optional, but recommended. Thus the file structure, zoomed +out, is: +
            +ha:{
            +	li:mouse { ... }
            +	li:main_menu { ... }
            +	li:popups { ... }
            +}
            +
            + +

            li:mouse

            +The mouse subtree may contain a li: for each mouse button action; +the children of the list are further li: nodes for key modifiers, whose +children are text nodes: actions executed in order. +

            +Buttons supported are: left, right, middle, up, down - the last two +are for the scroll wheel. Modifier name should start with "press" or "release" +optionally followed by modifier key suffixes separated with dashes, e.g. +"press-alt-shift" means the given button is pressed while alt and shift +were also pressed. +

            +Example structure: +

            +	li:mouse {
            +		li:left {
            +			li:press            = { Mode(Notify) }
            +			li:press-ctrl       = { Mode(Save); Mode(None); }
            +		}
            +	}
            +
            + +

            li:main_menu

            +The main menu is a list of menubar items that may host submenu items +recursively. Each normal item is a hash with the following children: +
              +
            • li:submenu an ordered list of submenu nodes (should not have accel key or action) +
            • tip tooltip text +
            • action text or list of actions to execute when menu is selected +
            • a a key description for an accelerator key (hotkey) +
            • li:a a list of key descriptions for an accelerator keys (hotkeys); all keys will be bound to the menu and the first key is shown in the menu +
            +Special menu items are text nodes instead of hashes; they are: +
              +
            • starting with @, are dynamic, auto-generated items (e.g. layers; might be HID-dependent) +
            • a single dash: separator +
            +

            +A key description is a text in the form of: +

              +
            • the name of the node is the visible name of the menu item +
            • <key>keyname, e.g. "<key>k" for key K, or "<key>F10" for F10 +
            • modifier<key>keyname, e.g. "Alt-<key>K" for Alt+K +
            • modifier-modifier<key>keyname, e.g. "Shift-Alt-<key>K" for Shift+Alt+K; modifiers are Alt, Shift and Ctrl; order does not matter, all three can be used together. +
            • multikey sequence: multiple of the above, separated by semicolons (protected with {} for lihata, as the text contains semicolon); e.g. "{<key>f;<key>o}" means the user presses "f" then "o". Sequences can be a dozen stroke long and any segment may use modifiers +
            + +An example menu item with submenus (can be a main menu or a submenu of +another menu item): +
            +ha:example menu item {
            +	li:submenu {
            +		ha:menu item {
            +			action=Save(ElementConnections)
            +			tip=example menu
            +		}
            +		-
            +		ha:another menu item {
            +			a={Shift-Alt<key>r}
            +			action={Action1(); Action2();}
            +		}
            +	}
            +}
            +
            + +

            li:popups

            +Each children is a hash that describes a popup menu. A popup menu behaves +exactly like a menu item, it should have a submenu list. Popup windows will +be popped up by executing an action with the name of the popup menu. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +The resource file format conversion is done. There are other parts of the code +that will probably get lihata instead of the current custom parsers, e.g. +the preferences/settings file. + + + Index: tags/1.2.7/doc/features/routings.html =================================================================== --- tags/1.2.7/doc/features/routings.html (nonexistent) +++ tags/1.2.7/doc/features/routings.html (revision 13657) @@ -0,0 +1,100 @@ + + + + pcb-rnd - routing style fixes + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - routing style fixes

            + +

            Number of styles

            +In the original code there are a compile-time fixed number (4) of routing +styles. This is often not enough for more complex designs. While in theory +this limit can be raised, the resulting .pcb files will be incompatible with +pcb compilations using a different number of styles. +

            +Pcb-rnd uses a dynamic vector for storing styles and allows any number +of styles from 0 up to a very large value (2^31-1). There is no compile-time +configurable limit. The number of default styles (and the actual style +configuration) is coming from the template pcb file. +

            +Creating a new style in the Route Styles dialog is not "for this session only" +anymore - styles are saved with the design. + +

            Explicit custom style

            +Pcb had 4 explicit styles and a hidden, implicit style. All drawing +action uses the hidden style. When the user selects one of the explicit +styles, its properties are copied into the implicit style. Any drawing +action uses the implicit style, this it's sort of the "pen style". +

            +In mainline PCB the implicit (or pen) style is hidden. As long as it always +matches one of the existing styles, the user doesn't even know about it. +However, if there are objects that do not conform to any of the existing +styles, it is possible to bump into this. For example: +

              +
            • draw a line using one of the existing styles +
            • increase the width (with the 's' key) a few times - now the style of the line does not match any of the existing styles +
            • use the SetSame() action over the line (hover the pointer over the line and press 'a') - it will try to set the style that corresponds to the line +
            • since no style matches the line's, the radio button gets deselected - that's good +
            • now click on the Route Style button - it will show the properties of the last selected route style, even tho it is not selected at the moment +
            +

            +In contrast, pcb-rnd offers an explicit routing style called <custom>. +If SetSame() is invoked on an object that doesn't match any of the existing styles, +the <custom> style is selected: +

              +
            • no style marked on the radio button (just like in mainline) +
            • the Route Style button opens with the <custom> style, with the values picked up from the object by SetSame +
            • the user can change the values, which will affect the implicit pen style +
            • this means the user can draw with the new settings, without having to create a permanent style +
            +

            +In other words, it is now possible to use the implicit pen style as temporal +style, to explicitly set a line width, via diameter before placing a few +unusual lines or vias, without having to create a new style. It is also +possible to pick up the style of such an unusual object later, without the +GUI confusing it with any of the existing styles. + +

            SetSame() bugs fixed

            +A line does not have drill parameters. When mainline tries to pick up +object properties for a line, it will pick thickness and clearance but +will leave hole and ring diameters unchanged. This very often results in +a mixed style: e.g. "signal" line properties picked up from a line while +"power" hole/ring properties left over from the current style selection. +Such a mixed pickup will result in the GUI get confused and not selecting any +of the styles. The expected behaviour is to select the "signal" style if the +line width/clearance matches the parameters of that style, and ignore the +drill/ring parameters. +

            +The same mixup happens for picking up arc parameters, and a similar mixup +for via parameters (a via doesn't have a line width). +

            +Pcb-rnd fixes this by searching for the matching style using only the parameters +that the given object really had. This results in valid style selection +the way the user may expect. + +

            save/load and compatibility

            +Saving a design with number of styles not equal to 4 may cause problems +when loading with mainline. The rest of these features do not affect +compatibility. + +

            plans

            +No plans - these features are fully implemented. + + Index: tags/1.2.7/doc/features/scconfig.html =================================================================== --- tags/1.2.7/doc/features/scconfig.html (nonexistent) +++ tags/1.2.7/doc/features/scconfig.html (revision 13657) @@ -0,0 +1,36 @@ + + + + pcb-rnd - [scconfig] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [scconfig] patch

            + +Pcb-rnd uses scconfig +for ./configure instead of autotools. Scconfig is smaller and easier +to maintain. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +No plans - this feature is fully implemented by now. + + Index: tags/1.2.7/doc/features/settings.html =================================================================== --- tags/1.2.7/doc/features/settings.html (nonexistent) +++ tags/1.2.7/doc/features/settings.html (revision 13657) @@ -0,0 +1,52 @@ + + + + pcb-rnd - different default settings + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - settings

            + +There are a few minor changes in default settings compared to mainline +pcb. + + + + + +
            name + description + where to change + +
            layers + the default layer stack is optimized for two sided boards with 3 layers on both sides + edit or replace /usr/share/pcb-rnd/default.pcb + +
            styles & DRC + default styles and DRC settings are optimized for toner transfer + edit or replace /usr/share/pcb-rnd/default.pcb + +
            grid + on startup "enable visible grid" is on and grid is set to 25 mil + change editor/draw_grid in pcb-conf.lht (in system install dir, in user dir) or in project.lht + +
            + + + Index: tags/1.2.7/doc/features/square.html =================================================================== --- tags/1.2.7/doc/features/square.html (nonexistent) +++ tags/1.2.7/doc/features/square.html (revision 13657) @@ -0,0 +1,96 @@ + + + + pcb-rnd - [square] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [square] patch

            + +

            Note: This feature is becoming useless with padstacks! + +

            +Most of my PCBs end up in toner transfer. There are a lot +of tricks around prototyping at home. One of the problems I often +face is small rings peeling off during rework (and rework tend to +happen on the first prototypes). The solution for this is increasing +ring size - which is not suitable if traces are passing between pins. +Another solution is to increase the area of the pin: +

              +
            • square pin: while it makes the pin slightly larger still letting traces pass between pins, it's too symmetrical and can not use up extra room +
            • DJ's teardrop plugin: this increases the area only toward the trace, whereas very often there's more room on the opposite side +
            • manually add an extra poly around the pin; with multiple pins it's hard to get the polys separate +
            • manually add a short extra track on the pin, width matching the size of the pin; this is very close, but increases workload when components are moved, layers are changed +
            +[demo showing DIP with different pin shapes] +

            +The patch takes an octagon pin and stretches points in various directions. +There are 4 bits (for left, right, up and down) to indicate in which directions +the stretch applies. Pressing 'q' on a pin cycles thru round pin, square pin, +16 stretched octagons and the original octagon. +

            +The code is also patched to handle clearances, shorts and connections (find.c). +

            +Thermals are not fully working for funny shaped pins, but it has low priority: +they still work fine for rounded and square pins and if there is a poly around +the pin, I wouldn't use shaped pins anyway. + +

            save/load and compatibility

            +This patch introduces a new pin flag called shape(n), where n is an integer +selecting the shape of the pin when the square flag is also set: +
            +Pin[40000 60000 6000 3000 6600 2800 "8" "8" "square,shape(3)"]
            +
            +Mainline PCB will load the design ignoring the custom shape and will use a +square pin. As long a traces end in the center point of the pin, this +should not break connections. +

            +Mainline PCB doesn't save shape() - once the design is loaded and saved with +mainline PCB pin shape info is lost. + +

            plans

            +In the original code there are separate code paths for round, octagonal and +square pins. The separation repeats for at least: +
              +
            • drawing the pin shape +
            • calculating the clearance +
            • checking whether things overlap or connect (pin vs pin, pin vs line, etc.) +
            • autorouter +
            +In most cases a set of hardwired constants are written in the C code. A notable +exception was the octagon pin draw function, that had x and y offsets in a const +table for 8 points and a loop to create the poly (or line segments in thin draw). +

            +The [square] feature is a good base for cleaning up the code a bit and for +moving toward a generic pin shape patch: +

              +
            • hardwired octagon calculations should be replaced to use the same x;y const offset table +
            • the table should be replaced by a struct that describes length (number of points) - alternatively use POLYAREA +
            • square pin should be renamed to polygon pin +
            • octagon flag shall be removed - it should be a configuration of the x;y const table +
            • square flag shall be removed - it should be a configuration +
            • the only flag remaining should be shape(); if a pin is not shaped, it's round +
            • the pin shape struct should have a field for compatibility - to mark the entry corresponding to the original square and octagon pins so PCB-rnd format can be converted to and from the mainline PCB format. +
            • there should be a set of pin shapes in a default configuration table, including square and octagonal; these should be static +
            • the PCB file format should be extended with an option to expand the pin shape table with custom shapes +
            • UI: shapes could be imported (converted) from polys around vias +
            • UI: since there may be a lot of pin shapes, a GUI selector alternative shall be offered while also keeping the cycle-thru 'q' key +
            + + Index: tags/1.2.7/doc/features/square.pcb =================================================================== --- tags/1.2.7/doc/features/square.pcb (nonexistent) +++ tags/1.2.7/doc/features/square.pcb (revision 13657) @@ -0,0 +1,893 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 130000 105000] + +Grid[2500.0 0 0 1] +Cursor[0 0 0.000000] +PolyArea[3100.006200] +Thermal[0.500000] +DRC[1000 1000 1000 1000 1500 1000] +Flags("nameonpcb,uniquename,clearnew") +Groups("1,c:2,s:3:4:5:6:7:8") +Styles["Signal,1500,6000,3150,2500:Power,3000,6000,3937,2500:Fat,8000,6000,3500,2500:Skinny,1200,2402,1181,2500"] + +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") + +Element["" "Dual in-line package, medium wide (400 mil)" "" "DIP14M" 62500 22500 22000 5000 3 100 ""] +( + Pin[0 0 6000 3000 6600 2800 "1" "1" "square"] + Pin[0 10000 6000 3000 6600 2800 "2" "2" ""] + Pin[0 20000 6000 3000 6600 2800 "3" "3" "thermal(1S)"] + Pin[0 30000 6000 3000 6600 2800 "4" "4" "square,shape(3)"] + Pin[0 40000 6000 3000 6600 2800 "5" "5" "square,shape(2)"] + Pin[0 50000 6000 3000 6600 2800 "6" "6" "square,shape(4)"] + Pin[0 60000 6000 3000 6600 2800 "7" "7" "square,shape(8)"] + Pin[40000 60000 6000 3000 6600 2800 "8" "8" "square,shape(8)"] + Pin[40000 50000 6000 3000 6600 2800 "9" "9" "square,shape(4)"] + Pin[40000 40000 6000 3000 6600 2800 "10" "10" "square,shape(2)"] + Pin[40000 30000 6000 3000 6600 2800 "11" "11" "square,shape(3)"] + Pin[40000 20000 6000 3000 6600 2800 "12" "12" ""] + Pin[40000 10000 6000 3000 6600 2800 "13" "13" ""] + Pin[40000 0 6000 3000 6600 2800 "14" "14" "square,shape(1)"] + ElementLine [-5000 -5000 -5000 65000 1000] + ElementLine [-5000 65000 45000 65000 1000] + ElementLine [45000 65000 45000 -5000 1000] + ElementLine [-5000 -5000 15000 -5000 1000] + ElementLine [25000 -5000 45000 -5000 1000] + ElementArc [20000 -5000 5000 5000 0 180 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( + Line[10000 17500 67500 17500 1500 5000 "clearline"] + Line[67500 17500 77500 27500 1500 5000 "clearline"] + Line[77500 27500 85000 27500 1500 5000 "clearline"] + Line[62500 22500 37500 22500 1500 5000 "clearline"] + Line[10000 27500 67500 27500 1500 5000 "clearline"] + Line[67500 27500 77500 37500 1500 5000 "clearline"] + Line[77500 37500 85000 37500 1500 5000 "clearline"] + Line[62500 32500 45000 32500 1500 5000 "clearline"] + Line[10000 37500 67500 37500 1500 5000 "clearline"] + Line[67500 37500 77500 47500 1500 5000 "clearline"] + Line[77500 47500 85000 47500 1500 5000 "clearline"] + Line[62500 42500 27500 42500 1500 5000 ""] + Line[10000 47500 67500 47500 1500 5000 "clearline"] + Line[67500 47500 77500 57500 1500 5000 "clearline"] + Line[77500 57500 85000 57500 1500 5000 "clearline"] + Line[62500 52500 37500 52500 1500 5000 "clearline"] + Line[37500 57500 67500 57500 1500 5000 "clearline"] + Line[67500 57500 77500 67500 1500 5000 "clearline"] + Line[77500 67500 85000 67500 1500 5000 "clearline"] + Line[62500 62500 37500 62500 1500 5000 "clearline"] + Line[37500 67500 67500 67500 1500 5000 "clearline"] + Line[67500 67500 77500 77500 1500 5000 "clearline"] + Line[77500 77500 85000 77500 1500 5000 "clearline"] + Line[62500 72500 37500 72500 1500 5000 "clearline"] + Line[37500 77500 67500 77500 1500 5000 "clearline"] + Line[67500 77500 77500 87500 1500 5000 "clearline"] + Line[77500 87500 85000 87500 1500 5000 "clearline"] + Line[62500 82500 37500 82500 1500 5000 "clearline"] + Line[65000 32500 60000 32500 6000 5000 "clearline"] + Line[105000 32500 100000 32500 6000 5000 "clearline"] + Line[102500 32500 125000 32500 1500 5000 "clearline"] + Line[102500 52500 125000 52500 1500 5000 "clearline"] + Line[102500 62500 125000 62500 1500 5000 "clearline"] + Line[102500 72500 125000 72500 1500 5000 "clearline"] + Line[102500 82500 125000 82500 1500 5000 "clearline"] + Line[102500 22500 125000 22500 1500 5000 "clearline"] + Polygon("clearpoly") + ( + [55000 37500] [70000 37500] [70000 47500] [55000 47500] + ) + Polygon("clearpoly") + ( + [85000 7500] [117500 7500] [117500 92500] [85000 92500] + ) +) +Layer(3 "GND") +( +) +Layer(4 "power") +( +) +Layer(5 "signal1") +( +) +Layer(6 "signal2") +( +) +Layer(7 "signal3") +( +) +Layer(8 "signal4") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Text[10000 17500 0 130 "square" "clearline"] + Text[10000 27500 0 130 "fat trace" "clearline"] + Text[10000 37500 0 130 "poly" "clearline"] + Text[25000 95000 1 130 "with [square]" "clearline"] + Text[15000 92500 1 130 "shaped pins" "clearline"] +) Index: tags/1.2.7/doc/features/square.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/features/square.png =================================================================== --- tags/1.2.7/doc/features/square.png (nonexistent) +++ tags/1.2.7/doc/features/square.png (revision 13657) Property changes on: tags/1.2.7/doc/features/square.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/features/tostyle.html =================================================================== --- tags/1.2.7/doc/features/tostyle.html (nonexistent) +++ tags/1.2.7/doc/features/tostyle.html (revision 13657) @@ -0,0 +1,74 @@ + + + + pcb-rnd - [tostyle] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [tostyle] patch

            + +

            TODO: This feature has to be revisited for padstacks! + +

            +Footprints bring their own hole sizes, copper ring sizes and clearances. +These parameters often depend on the manufacturing process, and such a value +coming from a footprint may differ much from the values used on the board already. +

            +PCB has actions (and menus and hotkeys) to change sizes manually. In my practice, +I try to stick to the sizes defined in my routing styles and try to avoid +manually changing clearances or ring sizes. Still, the random values coming +from various footprints should be changed. +

            +After many years of struggling with this, I realized the feature I need is +a way to change object sizes to not a relative or absolute number but +to the current routing style. The [tostyle] patch does exactly this. +It implements the following new features: +

              +
            • change clearance size now works on elements: it changes the clearance of all pins/pads; this is the same as change drill has been working for a long time +
            • size change actions normally take a value and a unit; if the value is not a number but text style, the value is copied from the currently active routing style +
            • a new ChangeSizes() action that attempts to execute the other three change size actions with the same arguments and fails only if all of them failed; the three sizes are: main size, drill size, clearance size +
            • a menu item and hotkey binding to key 'Shift+Y' (for routing stYle) that calls ChangeSizes() of the selected or current object(s) to resize them to the current routing style +
            +

            +The new route style set works on: +

              +
            • lines and arcs: sets their line width and clearance +
            • vias and individual pins: sets their ring dia, drill dia and clearance +
            • individual pads: sets their clearance +
            • elements: set all their pins and pads +
            + +

            Example

            +GUI: select a routing style; hover above a line, a via, a pin/pad of an element +or the silk of an element; press Shift+Y; undo if necessary. +

            +CLI: select objects, execute action ChangeSizes(selected, style) +

            +CLI: to adjust drill sizes only: select objects, execute action ChangeDrillSize(selected, style) + + +

            save/load and compatibility

            +Not affected, since the patch introduces actions and UI changes, no change +related to the data model. + +

            plans

            +No plans, the feature is complete. + + + Index: tags/1.2.7/doc/features/unglib.html =================================================================== --- tags/1.2.7/doc/features/unglib.html (nonexistent) +++ tags/1.2.7/doc/features/unglib.html (revision 13657) @@ -0,0 +1,38 @@ + + + + pcb-rnd - [unglib] + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [unglib] patch

            + +Removes glib dependency from core, in favor of +minilibs to help +keeping the code small, modular +and easier to fix. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Remove glib dependency from the puller plugin. + + + Index: tags/1.2.7/doc/help.html =================================================================== --- tags/1.2.7/doc/help.html (nonexistent) +++ tags/1.2.7/doc/help.html (revision 13657) @@ -0,0 +1,67 @@ + + + + pcb-rnd - help wanted + + + + + + + + + + +
            Main + News + Doc + 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: mail to pcb-rnd (at) igor2.repo.hu . +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 +
            doc user, html write sections of user documentation +
            logo designer the official pcb-rnd logo +
            banner designer pcb-rnd banner for the homepage +
            icons designer icons, other graphical elements for the GTK HID +
            css designer CSS for the homepage (only design/style, no content). +
            atest C/beginner program automated test cases +
            + + Index: tags/1.2.7/doc/index.html =================================================================== --- tags/1.2.7/doc/index.html (nonexistent) +++ tags/1.2.7/doc/index.html (revision 13657) @@ -0,0 +1,127 @@ + + + + pcb-rnd - main + + + + + + + + + + +
            Main + News + Doc + 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 +

            is feature-rich and compatible +

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

            Version Control svn://repo.hu/pcb-rnd/trunk +
            Download source releases +
            Comments, feedback, patches live chat with the developer
            or mail to: pcb-rnd (at) igor2.repo.hu
            Mailing list: pcb-rnd (at) list.repo.hu (send a mail with subject: subscribe) +
            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 + +
            Supported platforms + +
            + Linux desktop (various distributions, from source) +
            official packages in Debian and Ubuntu +
            Arch Linux (user package) +
            Mac OS X + +
            IRIX 5.3 +
            (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/1.2.7/doc/irc.html =================================================================== --- tags/1.2.7/doc/irc.html (nonexistent) +++ tags/1.2.7/doc/irc.html (revision 13657) @@ -0,0 +1,47 @@ + + + + pcb-rnd - IRC + + + + + + + + + + +
            Main + News + Doc + 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 may change your nickname; 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/1.2.7/doc/keys.html =================================================================== --- tags/1.2.7/doc/keys.html (nonexistent) +++ tags/1.2.7/doc/keys.html (revision 13657) @@ -0,0 +1,714 @@ + + + + + + Key to action bindings + + + + + +

            Key to action bindings

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            key pcb-menu-lesstif.lht pcb-menu-gtk.lht +
            . + 'All-direction' lines
            conf(toggle, editor/all_direction_lines, design) +
            'All-direction' lines
            conf(toggle, editor/all_direction_lines, design) +
            0 + Select Layer 10
            SelectLayer(10) +
            Select Layer 10
            SelectLayer(10) +
            0-alt + Select Layer 20
            SelectLayer(20) +
            Select Layer 20
            SelectLayer(20) +
            0-alt-ctrl + Toggle Layer 20
            ToggleView(20) +
            Toggle Layer 20
            ToggleView(20) +
            0-ctrl + Toggle Layer 10
            ToggleView(10) +
            Toggle Layer 10
            ToggleView(10) +
            1 + Select Layer 1
            SelectLayer(1) +
            Select Layer 1
            SelectLayer(1) +
            1-alt + Select Layer 11
            SelectLayer(11) +
            Select Layer 11
            SelectLayer(11) +
            1-alt-ctrl + Toggle Layer 11
            ToggleView(11) +
            Toggle Layer 11
            ToggleView(11) +
            1-ctrl + Toggle Layer 1
            ToggleView(1) +
            Toggle Layer 1
            ToggleView(1) +
            1-shift + #1
            PasteBuffer(1) +
            Select Buffer #1
            PasteBuffer(1) +
            2 + Select Layer 2
            SelectLayer(2) +
            Select Layer 2
            SelectLayer(2) +
            2-alt + Select Layer 12
            SelectLayer(12) +
            Select Layer 12
            SelectLayer(12) +
            2-alt-ctrl + Toggle Layer 12
            ToggleView(12) +
            Toggle Layer 12
            ToggleView(12) +
            2-ctrl + Toggle Layer 2
            ToggleView(2) +
            Toggle Layer 2
            ToggleView(2) +
            2-shift + #2
            PasteBuffer(2) +
            Select Buffer #2
            PasteBuffer(2) +
            3 + Select Layer 3
            SelectLayer(3) +
            Select Layer 3
            SelectLayer(3) +
            3-alt + Select Layer 13
            SelectLayer(13) +
            Select Layer 13
            SelectLayer(13) +
            3-alt-ctrl + Toggle Layer 13
            ToggleView(13) +
            Toggle Layer 13
            ToggleView(13) +
            3-ctrl + Toggle Layer 3
            ToggleView(3) +
            Toggle Layer 3
            ToggleView(3) +
            3-shift + #3
            PasteBuffer(3) +
            Select Buffer #3
            PasteBuffer(3) +
            4 + Select Layer 4
            SelectLayer(4) +
            Select Layer 4
            SelectLayer(4) +
            4-alt + Select Layer 14
            SelectLayer(14) +
            Select Layer 14
            SelectLayer(14) +
            4-alt-ctrl + Toggle Layer 14
            ToggleView(14) +
            Toggle Layer 14
            ToggleView(14) +
            4-ctrl + Toggle Layer 4
            ToggleView(4) +
            Toggle Layer 4
            ToggleView(4) +
            4-shift + #4
            PasteBuffer(4) +
            Select Buffer #4
            PasteBuffer(4) +
            5 + Select Layer 5
            SelectLayer(5) +
            Select Layer 5
            SelectLayer(5) +
            5-alt + Select Layer 15
            SelectLayer(15) +
            Select Layer 15
            SelectLayer(15) +
            5-alt-ctrl + Toggle Layer 15
            ToggleView(15) +
            Toggle Layer 15
            ToggleView(15) +
            5-ctrl + Toggle Layer 5
            ToggleView(5) +
            Toggle Layer 5
            ToggleView(5) +
            5-shift + #5
            PasteBuffer(5) +
            Select Buffer #5
            PasteBuffer(5) +
            6 + Select Layer 6
            SelectLayer(6) +
            Select Layer 6
            SelectLayer(6) +
            6-alt + Select Layer 16
            SelectLayer(16) +
            Select Layer 16
            SelectLayer(16) +
            6-alt-ctrl + Toggle Layer 16
            ToggleView(16) +
            Toggle Layer 16
            ToggleView(16) +
            6-ctrl + Toggle Layer 6
            ToggleView(6) +
            Toggle Layer 6
            ToggleView(6) +
            7 + Select Layer 7
            SelectLayer(7) +
            Select Layer 7
            SelectLayer(7) +
            7-alt + Select Layer 17
            SelectLayer(17) +
            Select Layer 17
            SelectLayer(17) +
            7-alt-ctrl + Toggle Layer 17
            ToggleView(17) +
            Toggle Layer 17
            ToggleView(17) +
            7-ctrl + Toggle Layer 7
            ToggleView(7) +
            Toggle Layer 7
            ToggleView(7) +
            8 + Select Layer 8
            SelectLayer(8) +
            Select Layer 8
            SelectLayer(8) +
            8-alt + Select Layer 18
            SelectLayer(18) +
            Select Layer 18
            SelectLayer(18) +
            8-alt-ctrl + Toggle Layer 18
            ToggleView(18) +
            Toggle Layer 18
            ToggleView(18) +
            8-ctrl + Toggle Layer 8
            ToggleView(8) +
            Toggle Layer 8
            ToggleView(8) +
            9 + Select Layer 9
            SelectLayer(9) +
            Select Layer 9
            SelectLayer(9) +
            9-alt + Select Layer 19
            SelectLayer(19) +
            Select Layer 19
            SelectLayer(19) +
            9-alt-ctrl + Toggle Layer 19
            ToggleView(19) +
            Toggle Layer 19
            ToggleView(19) +
            9-ctrl + Toggle Layer 9
            ToggleView(9) +
            Toggle Layer 9
            ToggleView(9) +
            : + Command
            Command() +
            Command Entry
            Command() +
            = + SimpleOpts
            djopt(simple) +
            Simple optimization
            djopt(simple) +
            =-ctrl + Auto-Optimize
            djopt(auto) +
            Auto-Optimize
            djopt(auto) +
            [ + Temp Arrow ON
            Mode(Save); Mode(Arrow); Mode(Notify) +
            Temp Arrow ON
            Mode(Save); Mode(Arrow); Mode(Notify) +
            \ +   + Full screen
            fullscreen(toggle) +
            / + Cycle Clip
            Display(CycleClip) +
            Cycle Clip
            Display(CycleClip) +
            ] + Temp Arrow OFF
            Mode(Release); Mode(Restore) +
            Temp Arrow OFF
            Mode(Release); Mode(Restore) +
            ` + Zoom Toggle
            Zoom(Toggle) +
              +
            a + Set Same
            SetSame() +
            Set Same
            SetSame() +
            a-alt + Select all visible
            Select(All) +
            Select all visible
            Select(All) +
            a-alt-shift + Unselect all
            Unselect(All) +
            Unselect all
            Unselect(All) +
            b + Flip Object
            Flip(Object) +
            Flip Object
            Flip(Object) +
            b-alt-ctrl +   + netlist patch for back annotation
            SavePatch() +
            b-shift + Move selected elements to other side
            Flip(SelectedElements) +
            Move selected elements to other side
            Flip(SelectedElements) +
            backspace + Remove
            Delete(Selected) +
            Remove Selected
            RemoveSelected() +
            backspace-shift + 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) +
            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 + Center cursor
            Center() +
            Center cursor
            Center() +
            c-alt + Route radius +0.5
            conf(delta, editor/route_radius, +0.5, design) +
            Route radius +0.5
            conf(delta, editor/route_radius, +0.5, design) +
            c-alt-shift + Route radius -0.5
            conf(delta, editor/route_radius, -0.5, design) +
            Route radius -0.5
            conf(delta, editor/route_radius, -0.5, design) +
            c-ctrl + Copy selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Mode(PasteBuffer) +
            Copy selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) +
            d + Pins/Via show Name/Number
            Display(PinOrPadName) +
            Pins/Via show Name/Number
            Display(PinOrPadName) +
            d-shift + Pinout
            Display(Pinout) +
            Error: key prefix collision +
            Pinout
            Display(Pinout) +
            delete + Delete selected objects
            Delete(Selected) +
            Remove
            Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) +
            delete-shift + 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) +
            Remove selected objects
            RemoveSelected() +
            down + Step Down
            Cursor(Warp,0,-1,grid) +
            Step Down
            Cursor(Warp,0,-1,grid) +
            down-shift + Step +Down
            Cursor(Pan,0,-50,view) +
            Step +Down
            Cursor(Pan,0,-50,view) +
            e + Erase rats-nest
            DeleteRats(AllRats) +
            Erase rats nest
            DeleteRats(AllRats) +
            e-ctrl +   + Edit properties of selected...
            PropEdit(Selected) +
            e-shift + Erase selected rats
            DeleteRats(SelectedRats) +
            Erase selected rats
            DeleteRats(SelectedRats) +
            enter + "Click"
            Mode(Notify); Mode(Release) +
            Click
            Mode(Notify); Mode(Release) +
            escape + Cancel
            Mode(Cancel) +
            Cancel
            Mode(Escape) +
            f + Find Connections
            Connection(Reset); Connection(Find) +
            Find Connections
            Connection(Reset); Connection(Find) +
            f-alt-ctrl + Change font on layout
            FontSel(Object) +
            Change font on layout
            FontSel(Object) +
            f-alt-shift +   + Replace footprint
            ReplaceFootprint() +
            f-ctrl + Lookup connection to object
            GetXY(Click on the object); Connection(Find) +
            Lookup connection to object
            GetXY(Click on the object); Connection(Find) +
            f-ctrl-shift + Font selector
            FontSel() +
            Font selector
            FontSel() +
            f-shift + Reset all connections
            Connection(Reset); Display(Redraw) +
            Reset all connections
            Connection(Reset); Display(Redraw) +
            f1 + Via
            Mode(Via) +
            Via
            Mode(Via) +
            f10 + Thermal
            Mode(Thermal) +
            Thermal
            Mode(Thermal) +
            f11 + Arrow
            Mode(Arrow) +
            Arrow
            Mode(Arrow) +
            f12 + Lock
            Mode(Lock) +
            Lock
            Mode(Lock) +
            f2 + Line
            Mode(Line) +
            Line
            Mode(Line) +
            f3 + Arc
            Mode(Arc) +
            Arc
            Mode(Arc) +
            f4 + Text
            Mode(Text) +
            Text
            Mode(Text) +
            f5 + Rectangle
            Mode(Rectangle) +
            Rectangle
            Mode(Rectangle) +
            f6 + Polygon
            Mode(Polygon) +
            Polygon
            Mode(Polygon) +
            f7 + Buffer
            Mode(PasteBuffer) +
            Buffer
            Mode(PasteBuffer) +
            f7-shift + Rotate buffer 90 deg CCW
            Mode(PasteBuffer); PasteBuffer(Rotate,1) +
            Rotate buffer 90 deg CCW
            Mode(PasteBuffer); PasteBuffer(Rotate,1) +
            f8 + Remove
            Mode(Remove) +
            Remove
            Mode(Remove) +
            f9 + Rotate
            Mode(Rotate) +
            Rotate
            Mode(Rotate) +
            g + Grid +5mil
            SetValue(Grid,+5,mil) +
            Grid +5mil
            SetValue(Grid,+5,mil) +
            g-ctrl + Grid +0.05mm
            SetValue(Grid,+0.05,mm) +
            Grid +0.05mm
            SetValue(Grid,+0.05,mm) +
            g-ctrl-shift + Grid -0.05mm
            SetValue(Grid,-0.05,mm) +
            Grid -0.05mm
            SetValue(Grid,-0.05,mm) +
            g-shift + Grid -5mil
            SetValue(Grid,-5,mil) +
            Grid -5mil
            SetValue(Grid,-5,mil) +
            h + ToggleHideName Object
            ToggleHideName(Object) +
            ToggleHideName Object
            ToggleHideName(Object) +
            h-ctrl + ChangeHole Object
            ChangeHole(Object) +
            ChangeHole Object
            ChangeHole(Object) +
            h-shift + ToggleHideName SelectedElement
            ToggleHideName(SelectedElements) +
            ToggleHideName SelectedElement
            ToggleHideName(SelectedElements) +
            i +   + Library
            DoWindows(Library) +
            insert + Insert Point
            Mode(InsertPoint) +
            Insert Point
            Mode(InsertPoint) +
            j + ChangeJoin Object
            ChangeJoin(Object) +
            ChangeJoin Object
            ChangeJoin(Object) +
            j-shift + ChangeJoin SelectedObject
            ChangeJoin(SelectedObjects) +
            ChangeJoin SelectedObject
            ChangeJoin(SelectedObjects) +
            k + Clear Object +2 mil
            ChangeClearSize(Object,+2,mil) +
            Clear Object +2 mil
            ChangeClearSize(Object,+2,mil) +
            k-ctrl + Clear Selected +2 mil
            ChangeClearSize(SelectedObjects,+2,mil) +
            Clear Selected +2 mil
            ChangeClearSize(SelectedObjects,+2,mil) +
            k-ctrl-shift + Clear Selected -2 mil
            ChangeClearSize(SelectedObjects,-2,mil) +
            Clear Selected -2 mil
            ChangeClearSize(SelectedObjects,-2,mil) +
            k-shift + Clear Object -2 mil
            ChangeClearSize(Object,-2,mil) +
            Clear Object -2 mil
            ChangeClearSize(Object,-2,mil) +
            l + Line Tool size +5 mil
            SetValue(LineSize,+5,mil) +
            Line Tool size +5 mil
            SetValue(LineSize,+5,mil) +
            l-shift + Line Tool size -5 mil
            SetValue(LineSize,-5,mil) +
            Line Tool size -5 mil
            SetValue(LineSize,-5,mil) +
            left + Step Left
            Cursor(Warp,-1,0,grid) +
            Step Left
            Cursor(Warp,-1,0,grid) +
            left-shift + Step +Left
            Cursor(Pan,-50,0,view) +
            Step +Left
            Cursor(Pan,-50,0,view) +
            m + Move Object to current layer
            MoveToCurrentLayer(Object) +
            Move Object to current layer
            MoveToCurrentLayer(Object) +
            m-ctrl + MarkCrosshair
            MarkCrosshair() +
            MarkCrosshair
            MarkCrosshair() +
            m-shift + Move selected to current layer
            MoveToCurrentLayer(Selected) +
            Move selected to current layer
            MoveToCurrentLayer(Selected) +
            n + Change text on layout
            ChangeName(Object) +
            text on layout
            ChangeName(Object) +
            n-alt +   + Nonetlist
            ChangeNonetlist(Element) +
            n-ctrl + Start new layout
            New() +
            Start New Layout
            New() +
            n-ctrl-shift + Change number on layout
            ChangeName(Object, Number) +
            pin on layout
            ChangeName(Object, Number) +
            n-shift + Select shortest rat
            AddRats(Close) +
            Select shortest rat
            AddRats(Close) +
            o + Optimize rats-nest
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block) +
            Optimize rats nest
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block) +
            o-ctrl + ChangeOctagon Object
            ChangeOctagon(Object) +
            ChangeOctagon Object
            ChangeOctagon(Object) +
            o-shift + AddRats to selected pins
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block) +
            AddRats to selected pins
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block) +
            p + Polygon PreviousPoint
            Polygon(PreviousPoint) +
            Polygon PreviousPoint
            Polygon(PreviousPoint) +
            p-alt + Manage plugins...
            ManagePlugins() +
            Manage plugins...
            ManagePlugins() +
            p-ctrl + Auto-place selected elements
            AutoPlaceSelected() +
            Auto-place selected elements
            AutoPlaceSelected() +
            p-ctrl-shift + Thin draw poly
            conf(toggle, editor/thin_draw_poly, design) +
            Thin draw poly
            conf(toggle, editor/thin_draw_poly, design) +
            p-shift + Polygon Close
            Polygon(Close) +
            Polygon Close
            Polygon(Close) +
            q + ChangeSquare Object
            ChangeSquare(Object) +
            ChangeSquare Object
            ChangeSquare(ToggleObject) +
            q-ctrl + Quit Program
            Quit() +
            Quit Program
            Quit() +
            r + Report net length
            Report(NetLength) +
              +
            r-alt + Auto-route selected rats
            AutoRoute(SelectedRats) +
            Auto-route selected rats
            AutoRoute(SelectedRats) +
            r-ctrl + Generate object report
            ReportObject() +
            Generate object report
            ReportObject() +
            r-shift + Redo last undone operation
            Redo() +
            Redo last undone operation
            Redo() +
            right + Step Right
            Cursor(Warp,1,0,grid) +
            Step Right
            Cursor(Warp,1,0,grid) +
            right-shift + Step +Right
            Cursor(Pan,50,0,view) +
            Step +Right
            Cursor(Pan,50,0,view) +
            s + ChangeSize +5 mil
            ChangeSize(Object,+5,mil) +
            ChangeSize +5 mil
            ChangeSize(Object,+5,mil) +
            s-alt + ChangeDrill +5 mil
            ChangeDrillSize(Object,+5,mil) +
            ChangeDrill +5 mil
            ChangeDrillSize(Object,+5,mil) +
            s-alt-shift + ChangeDrill -5 mil
            ChangeDrillSize(Object,-5,mil) +
            ChangeDrill -5 mil
            ChangeDrillSize(Object,-5,mil) +
            s-ctrl + Save layout
            Save(Layout) +
            Save Layout
            Save(Layout) +
            s-ctrl-shift + Save layout as...
            Save(LayoutAs) +
            Save Layout As...
            Save(LayoutAs) +
            s-shift + ChangeSize -5 mil
            ChangeSize(Object,-5,mil) +
            ChangeSize -5 mil
            ChangeSize(Object,-5,mil) +
            space + Arrow
            Mode(Arrow) +
            Arrow Mode
            Mode(Arrow) +
            t + Text Tool scale +10 mil
            SetValue(TextScale,+10,mil) +
            Text Tool scale +10 mil
            SetValue(TextScale,+10,mil) +
            t-shift + Text Tool scale -10 mil
            SetValue(TextScale,-10,mil) +
            Text Tool scale -10 mil
            SetValue(TextScale,-10,mil) +
            tab + Flip up/down
            SwapSides(V) +
            Flip up/down
            SwapSides(V) +
            tab-ctrl + Spin 180°
            SwapSides(R) +
            Spin 180 degrees
            SwapSides(R) +
            tab-ctrl-shift + Swap Sides
            SwapSides() +
            Swap Sides
            SwapSides() +
            tab-shift + Flip left/right
            SwapSides(H) +
            Flip left/right
            SwapSides(H) +
            u + Undo last operation
            Undo() +
            Undo last operation
            Undo() +
            u-ctrl-shift + Clear undo-buffer
            Undo(ClearList) +
            Clear undo-buffer
            Undo(ClearList) +
            up + Step Up
            Cursor(Warp,0,1,grid) +
            Step Up
            Cursor(Warp,0,1,grid) +
            up-shift + Step +Up
            Cursor(Pan,0,50,view) +
            Step +Up
            Cursor(Pan,0,50,view) +
            v + Zoom Max
            Zoom() +
            Zoom Max
            Zoom() +
            v-alt + Via Tool drill +5 mil
            SetValue(ViaDrillingHole,+5,mil) +
            Via Tool drill +5 mil
            SetValue(ViaDrillingHole,+5,mil) +
            v-alt-shift + Via Tool drill -5 mil
            SetValue(ViaDrillingHole,-5,mil) +
            Via Tool drill -5 mil
            SetValue(ViaDrillingHole,-5,mil) +
            v-ctrl + Paste buffer to layout
            Mode(PasteBuffer) +
            Paste buffer to layout
            Mode(PasteBuffer) +
            v-ctrl-shift + Via Tool size -5 mil
            SetValue(ViaSize,-5,mil) +
            Via Tool size -5 mil
            SetValue(ViaSize,-5,mil) +
            v-shift + Via Tool size +5 mil
            SetValue(ViaSize,+5,mil) +
            Via Tool size +5 mil
            SetValue(ViaSize,+5,mil) +
            w + Add All Rats
            AddRats(AllRats) +
            Add All Rats
            AddRats(AllRats) +
            w-ctrl + Wireframe draw
            conf(toggle, editor/wireframe_draw, design) +
            Wireframe draw
            conf(toggle, editor/wireframe_draw, design) +
            w-shift + AddRats Selected
            AddRats(SelectedRats) +
            AddRats Selected
            AddRats(SelectedRats) +
            x +   + Cycle object being dragged
            CycleDrag() +
            x-ctrl + Cut selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) +
            Cut selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); RemoveSelected(); Mode(PasteBuffer) +
            x-shift +   + Swap nets on two selected pins
            net(swap) +
            y + Puller
            Puller() +
            Puller
            Puller() +
            y-shift + ChangeSizes to Route style
            ChangeSizes(Object,style,mil) +
            ChangeSizes to Route style
            ChangeSizes(Object,style,mil) +
            z + Zoom In 20%
            Zoom(-1.2) +
            Zoom In 20%
            Zoom(-1.2) +
            z-alt + Undo
            Undo() +
              +
            z-shift + Zoom Out 20%
            Zoom(+1.2) +
            Zoom Out 20%
            Zoom(+1.2) +
            | + Thin draw
            conf(toggle, editor/thin_draw, design) +
            Thin draw
            conf(toggle, editor/thin_draw, design) +
            +
            pcb-menu-lesstif.lht: d-shift vs. d-shift; + Index: tags/1.2.7/doc/keys_mkey.html =================================================================== --- tags/1.2.7/doc/keys_mkey.html (nonexistent) +++ tags/1.2.7/doc/keys_mkey.html (revision 13657) @@ -0,0 +1,599 @@ + + + + + + Key to action bindings + + + + + +

            Key to action bindings

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            key pcb-menu-mkey.lht +
            . + '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) +
            1-shift + File/Buffer/Select Buffer #1
            PasteBuffer(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) +
            2-shift + File/Buffer/Select Buffer #2
            PasteBuffer(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) +
            3-shift + File/Buffer/Select Buffer #3
            PasteBuffer(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) +
            4-shift + File/Buffer/Select Buffer #4
            PasteBuffer(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) +
            5-shift + File/Buffer/Select Buffer #5
            PasteBuffer(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() +
            = + Simple optimization
            djopt(simple) +
            =-ctrl + Auto-Optimize
            djopt(auto) +
            [ + Grid -5mil
            SetValue(Grid,-5,mil) +
            \ + Full screen
            fullscreen(toggle) +
            / + Cycle Clip
            Display(CycleClip) +
            ] + Grid +5mil
            SetValue(Grid,+5,mil) +
            a-alt + Select all visible
            Select(All) +
            a-alt-shift + Unselect all
            Unselect(All) +
            a
             c +
            Library
            DoWindows(Library) +
            a
             l +
            Line
            Mode(Line) +
            a
             n +
            Line
            Mode(Line) +
            a
             p +
            Rectangle
            Mode(Rectangle) +
            a
             r +
            Arc
            Mode(Arc) +
            a
             t +
            Text
            Mode(Text) +
            a
             v +
            Rectangle
            Mode(Rectangle) +
            b + Flip Object
            Flip(Object) +
            b-alt-ctrl + a single element/netlist patch for back annotation
            SavePatch() +
            b-shift + Move selected elements to other side
            Flip(SelectedElements) +
            backspace + Remove Selected
            RemoveSelected() +
            backspace-shift + 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 + Center cursor
            Center() +
            c-alt + Route radius +0.5
            conf(delta, editor/route_radius, +0.5, design) +
            c-alt-shift + Route radius -0.5
            conf(delta, editor/route_radius, -0.5, design) +
            c-ctrl
              +
            Copy selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(AddSelected); Unselect(All); Mode(PasteBuffer) +
            d + Pins/Via show Name/Number
            Display(PinOrPadName) +
            d-shift + Pinout
            Display(Pinout) +
            delete + Remove
            Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) +
            delete-shift + Remove selected objects
            RemoveSelected() +
            down + Step Down
            Cursor(Warp,0,-1,grid) +
            down-shift + Step +Down
            Cursor(Pan,0,-50,view) +
            e-shift + Erase selected rats
            DeleteRats(SelectedRats) +
            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
            Mode(Save); Mode(Remove); Mode(Notify); Mode(Restore) +
            e
             f +
            Edit name of/Change font on layout
            FontSel(Object) +
            e
             i +
            File/Buffer/Mirror buffer (up/down)
            Mode(PasteBuffer); PasteBuffer(Mirror) +
            e
             l +
            Lock
            Mode(Lock) +
            e
             l-shift +
            Lock
            Mode(Lock) +
            e
             r +
            Rotate buffer 90 deg CCW
            +
            e
             r-shift +
            Redo last undone operation
            Redo() +
            e
             u-shift +
            Undo last operation
            Undo() +
            e
             x +
            text on layout
            ChangeName(Object) +
            enter + Click
            Mode(Notify); Mode(Release) +
            escape + Cancel
            Mode(Escape) +
            f-alt-shift + Replace footprint
            ReplaceFootprint() +
            f-ctrl + Lookup connection to object
            GetXY(Click on the object); Connection(Find) +
            f-ctrl-shift + Font selector
            FontSel() +
            f-shift + Reset all connections
            Connection(Reset); Display(Redraw) +
            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) +
            f8 + Remove
            Mode(Remove) +
            f9 + Rotate
            Mode(Rotate) +
            f
             a +
            Save Layout As...
            Save(LayoutAs) +
            f
             c +
            Save connection data of/Quit Program
            Quit() +
            f
             i +
            Save connection data of/Export layout...
            ExportGUI() +
            f
             n +
            Start New Layout
            New() +
            f
             o +
            Load layout
            Load(Layout) +
            f
             p +
            Save connection data of/Print layout...
            Print() +
            f
             r +
            Revert
            Load(Revert,none) +
            f
             s +
            Save Layout
            Save(Layout) +
            g + Grid +5mil
            SetValue(Grid,+5,mil) +
            g-ctrl + Grid +0.05mm
            SetValue(Grid,+0.05,mm) +
            g-ctrl-shift + Grid -0.05mm
            SetValue(Grid,-0.05,mm) +
            g-shift + Grid -5mil
            SetValue(Grid,-5,mil) +
            h-ctrl + ChangeHole Object
            ChangeHole(Object) +
            h-shift + ToggleHideName SelectedElement
            ToggleHideName(SelectedElements) +
            h
             a +
            About...
            About() +
            insert + Insert Point
            Mode(InsertPoint) +
            j + ChangeJoin Object
            ChangeJoin(Object) +
            j-shift + ChangeJoin SelectedObject
            ChangeJoin(SelectedObjects) +
            k + Clear Object +2 mil
            ChangeClearSize(Object,+2,mil) +
            k-ctrl + Clear Selected +2 mil
            ChangeClearSize(SelectedObjects,+2,mil) +
            k-ctrl-shift + Clear Selected -2 mil
            ChangeClearSize(SelectedObjects,-2,mil) +
            k-shift + Clear Object -2 mil
            ChangeClearSize(Object,-2,mil) +
            l + Line Tool size +5 mil
            SetValue(LineSize,+5,mil) +
            l-shift + Line Tool size -5 mil
            SetValue(LineSize,-5,mil) +
            left + Step Left
            Cursor(Warp,-1,0,grid) +
            left-shift + Step +Left
            Cursor(Pan,-50,0,view) +
            m + Move Object to current layer
            MoveToCurrentLayer(Object) +
            m-ctrl + MarkCrosshair
            MarkCrosshair() +
            m-shift + Move selected to current layer
            MoveToCurrentLayer(Selected) +
            n + text on layout
            ChangeName(Object) +
            n-alt + Nonetlist
            ChangeNonetlist(Element) +
            n-ctrl + Start New Layout
            New() +
            n-ctrl-shift + pin on layout
            ChangeName(Object, Number) +
            n-shift + Select shortest rat
            AddRats(Close) +
            o + Optimize rats nest
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(AllRats); Atomic(Block) +
            o-ctrl + ChangeOctagon Object
            ChangeOctagon(Object) +
            o-shift + AddRats to selected pins
            Atomic(Save); DeleteRats(AllRats); Atomic(Restore); AddRats(SelectedRats); Atomic(Block) +
            p + Polygon PreviousPoint
            Polygon(PreviousPoint) +
            p-alt + Manage plugins...
            ManagePlugins() +
            p-ctrl + Auto-place selected elements
            AutoPlaceSelected() +
            p-ctrl-shift + Thin draw poly
            conf(toggle, editor/thin_draw_poly, design) +
            p-shift + Polygon Close
            Polygon(Close) +
            q + ChangeSquare Object
            ChangeSquare(ToggleObject) +
            q-ctrl + Save connection data of/Quit Program
            Quit() +
            r-alt + Auto-route selected rats
            AutoRoute(SelectedRats) +
            r-ctrl + Generate object report
            ReportObject() +
            r-shift + Redo last undone operation
            Redo() +
            right + Step Right
            Cursor(Warp,1,0,grid) +
            right-shift + Step +Right
            Cursor(Pan,50,0,view) +
            s + ChangeSize +5 mil
            ChangeSize(Object,+5,mil) +
            s-alt + ChangeDrill +5 mil
            ChangeDrillSize(Object,+5,mil) +
            s-alt-shift + ChangeDrill -5 mil
            ChangeDrillSize(Object,-5,mil) +
            s-ctrl + Save Layout
            Save(Layout) +
            s-ctrl-shift + Save Layout As...
            Save(LayoutAs) +
            s-shift + ChangeSize -5 mil
            ChangeSize(Object,-5,mil) +
            space + Arrow Mode
            Mode(Arrow) +
            t + Text Tool scale +10 mil
            SetValue(TextScale,+10,mil) +
            t-shift + Text Tool scale -10 mil
            SetValue(TextScale,-10,mil) +
            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 + Undo last operation
            Undo() +
            u-ctrl-shift + Clear undo-buffer
            Undo(ClearList) +
            up + Step Up
            Cursor(Warp,0,1,grid) +
            up-shift + Step +Up
            Cursor(Pan,0,50,view) +
            v-alt + Via Tool drill +5 mil
            SetValue(ViaDrillingHole,+5,mil) +
            v-alt-shift + Via Tool drill -5 mil
            SetValue(ViaDrillingHole,-5,mil) +
            v-ctrl + Paste buffer to layout
            Mode(PasteBuffer) +
            v-ctrl-shift + Via Tool size -5 mil
            SetValue(ViaSize,-5,mil) +
            v-shift + Via Tool size +5 mil
            SetValue(ViaSize,+5,mil) +
            v
             e +
            Zoom Max
            Zoom() +
            v
             f +
            Zoom Max
            Zoom() +
            v
             i +
            Zoom In 2X
            Zoom(-2) +
            v
             o +
            Zoom Out 2X
            Zoom(+2) +
            w + Add All Rats
            AddRats(AllRats) +
            w-ctrl + Wireframe draw
            conf(toggle, editor/wireframe_draw, design) +
            w-shift + AddRats Selected
            AddRats(SelectedRats) +
            x + Cycle object being dragged
            CycleDrag() +
            x-ctrl + Cut selection to buffer
            GetXY(Click to set the snap point for this buffer); PasteBuffer(Clear); PasteBuffer(MoveSelected); Mode(PasteBuffer) +
            x-shift + Swap nets on two selected pins
            net(swap) +
            y + Puller
            Puller() +
            y-ctrl + Redo last undone operation
            Redo() +
            y-shift + ChangeSizes to Route style
            ChangeSizes(Object,style,mil) +
            z + Zoom In 20%
            Zoom(-1.2) +
            z-ctrl + Undo last operation
            Undo() +
            z-shift + Zoom Out 20%
            Zoom(+1.2) +
            | + Thin draw
            conf(toggle, editor/thin_draw, design) +
            + + Index: tags/1.2.7/doc/license.html =================================================================== --- tags/1.2.7/doc/license.html (nonexistent) +++ tags/1.2.7/doc/license.html (revision 13657) @@ -0,0 +1,56 @@ + + + + pcb-rnd - license + + + + + + + + + + +
            Main + News + Doc + 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/1.2.7/doc/mac.txt =================================================================== --- tags/1.2.7/doc/mac.txt (nonexistent) +++ tags/1.2.7/doc/mac.txt (revision 13657) @@ -0,0 +1,22 @@ +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+ + * 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. Index: tags/1.2.7/doc/man/Makefile =================================================================== --- tags/1.2.7/doc/man/Makefile (nonexistent) +++ tags/1.2.7/doc/man/Makefile (revision 13657) @@ -0,0 +1,62 @@ +# 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 +OUT_HTML = pcb-rnd.1.html pcb-strip.1.html pcb-prj2lht.1.html fp2anim.1.html +OUT_MAN1 = pcb-rnd.1 pcb-strip.1 pcb-prj2lht.1 fp2anim.1 +OUT_LINT = pcb-rnd.1.lint pcb-strip.1.lint pcb-prj2lht.1.lint fp2anim.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" + +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/1.2.7/doc/man/README =================================================================== --- tags/1.2.7/doc/man/README (nonexistent) +++ tags/1.2.7/doc/man/README (revision 13657) @@ -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/1.2.7/doc/man/copyright.mml =================================================================== --- tags/1.2.7/doc/man/copyright.mml (nonexistent) +++ tags/1.2.7/doc/man/copyright.mml (revision 13657) @@ -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[removethis]@igor2.repo.hu + +pcb-rnd manual Index: tags/1.2.7/doc/man/fp2anim.1 =================================================================== --- tags/1.2.7/doc/man/fp2anim.1 (nonexistent) +++ tags/1.2.7/doc/man/fp2anim.1 (revision 13657) @@ -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[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/1.2.7/doc/man/fp2anim.1.html =================================================================== --- tags/1.2.7/doc/man/fp2anim.1.html (nonexistent) +++ tags/1.2.7/doc/man/fp2anim.1.html (revision 13657) @@ -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/1.2.7/doc/man/fp2anim.1.mml =================================================================== --- tags/1.2.7/doc/man/fp2anim.1.mml (nonexistent) +++ tags/1.2.7/doc/man/fp2anim.1.mml (revision 13657) @@ -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/1.2.7/doc/man/gsch2pcb-rnd.1 =================================================================== --- tags/1.2.7/doc/man/gsch2pcb-rnd.1 (nonexistent) +++ tags/1.2.7/doc/man/gsch2pcb-rnd.1 (revision 13657) @@ -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/1.2.7/doc/man/index.html =================================================================== --- tags/1.2.7/doc/man/index.html (nonexistent) +++ tags/1.2.7/doc/man/index.html (revision 13657) @@ -0,0 +1,7 @@ + +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 +
            Index: tags/1.2.7/doc/man/pcb-prj2lht.1 =================================================================== --- tags/1.2.7/doc/man/pcb-prj2lht.1 (nonexistent) +++ tags/1.2.7/doc/man/pcb-prj2lht.1 (revision 13657) @@ -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[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/1.2.7/doc/man/pcb-prj2lht.1.html =================================================================== --- tags/1.2.7/doc/man/pcb-prj2lht.1.html (nonexistent) +++ tags/1.2.7/doc/man/pcb-prj2lht.1.html (revision 13657) @@ -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/1.2.7/doc/man/pcb-prj2lht.1.mml =================================================================== --- tags/1.2.7/doc/man/pcb-prj2lht.1.mml (nonexistent) +++ tags/1.2.7/doc/man/pcb-prj2lht.1.mml (revision 13657) @@ -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/1.2.7/doc/man/pcb-rnd.1 =================================================================== --- tags/1.2.7/doc/man/pcb-rnd.1 (nonexistent) +++ tags/1.2.7/doc/man/pcb-rnd.1 (revision 13657) @@ -0,0 +1,47 @@ +.\" 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[removethis]@igor2.repo.hu +.TH pcb-rnd 1 2016-10-29 "" "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 -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/1.2.7/doc/man/pcb-rnd.1.html =================================================================== --- tags/1.2.7/doc/man/pcb-rnd.1.html (nonexistent) +++ tags/1.2.7/doc/man/pcb-rnd.1.html (revision 13657) @@ -0,0 +1,83 @@ + + + +pcb-rnd - pcb-rnd manual + + + + +
            pcb-rnd 1 + 2016-10-29 + 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

            +
            + + + + + + + + + +
            -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 + 2016-10-29 + pcb-rnd manual +
            + + + Index: tags/1.2.7/doc/man/pcb-rnd.1.mml =================================================================== --- tags/1.2.7/doc/man/pcb-rnd.1.mml (nonexistent) +++ tags/1.2.7/doc/man/pcb-rnd.1.mml (revision 13657) @@ -0,0 +1,38 @@ +pcb-rnd +1 +2016-10-29 + + 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. + + + + + + -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/1.2.7/doc/man/pcb-strip.1 =================================================================== --- tags/1.2.7/doc/man/pcb-strip.1 (nonexistent) +++ tags/1.2.7/doc/man/pcb-strip.1 (revision 13657) @@ -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[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/1.2.7/doc/man/pcb-strip.1.html =================================================================== --- tags/1.2.7/doc/man/pcb-strip.1.html (nonexistent) +++ tags/1.2.7/doc/man/pcb-strip.1.html (revision 13657) @@ -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/1.2.7/doc/man/pcb-strip.1.mml =================================================================== --- tags/1.2.7/doc/man/pcb-strip.1.mml (nonexistent) +++ tags/1.2.7/doc/man/pcb-strip.1.mml (revision 13657) @@ -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/1.2.7/doc/motivation.html =================================================================== --- tags/1.2.7/doc/motivation.html (nonexistent) +++ tags/1.2.7/doc/motivation.html (revision 13657) @@ -0,0 +1,128 @@ + + + + pcb-rnd - motivation + + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd motivation

            + +

            Phase 4: expansion (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 (manu.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 is already implemented) +
              • 1206 jumpers without having to add them on the schematics/netlist (done: [intconn] and [nonetlist] are the PCB-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 ) +
              +
            +

            +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/1.2.7/doc/myfeature.html =================================================================== --- tags/1.2.7/doc/myfeature.html (nonexistent) +++ tags/1.2.7/doc/myfeature.html (revision 13657) @@ -0,0 +1,77 @@ + + + + pcb-rnd - my feature + + + + + + + + + + +
            Main + News + Doc + 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%. + + + +

            4. If you don't have anything to contribute with

            +[DEL:Vote for it in the +feature poll. If your feature is not there, ask on the mailing list. +Chance for success: if it's a popular demand on the feature poll, chances +are somewhat good. Else chances are very low, but not zero.:DEL] +

            +Because of 100% passivity of the geda community, I decided not to spend more +time on community-related tasks there. The poll is available, you can use it, +but you will have to organize at least 5 active, capable users who are +committed enough to spend significant time on testing/supporting development. +I will consider implementing your feature only if you can bring and keep +those people motivated and active. + +

            5. If you tried everything, even point 4. and all failed...

            +Complain loudly on the mailing list, advertise your opinion, try pushing +the thing - a.k.a. go trolling. Success rate is exactly 0%, +you make a lot of good friends enemies that will make it harder +to ask or contribute later for another feature, but it may make you feel +better. </irony>. + Index: tags/1.2.7/doc/news.html =================================================================== --- tags/1.2.7/doc/news.html (nonexistent) +++ tags/1.2.7/doc/news.html (revision 13657) @@ -0,0 +1,155 @@ + + + + pcb-rnd - news + + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +
            + +

            News

            + +
            + + + + + + + + + + + + + + + +
            + 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/1.2.7/doc/plan.txt =================================================================== --- tags/1.2.7/doc/plan.txt (nonexistent) +++ tags/1.2.7/doc/plan.txt (revision 13657) @@ -0,0 +1,136 @@ +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] + GPMI scripting yes, buildin [gpmi] y + 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/1.2.7/doc/resources/logo.pcb =================================================================== --- tags/1.2.7/doc/resources/logo.pcb (nonexistent) +++ tags/1.2.7/doc/resources/logo.pcb (revision 13657) @@ -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/1.2.7/doc/resources/logo128.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/logo128.png =================================================================== --- tags/1.2.7/doc/resources/logo128.png (nonexistent) +++ tags/1.2.7/doc/resources/logo128.png (revision 13657) Property changes on: tags/1.2.7/doc/resources/logo128.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/resources/logo16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/logo16.png =================================================================== --- tags/1.2.7/doc/resources/logo16.png (nonexistent) +++ tags/1.2.7/doc/resources/logo16.png (revision 13657) Property changes on: tags/1.2.7/doc/resources/logo16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/resources/logo256.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/logo256.png =================================================================== --- tags/1.2.7/doc/resources/logo256.png (nonexistent) +++ tags/1.2.7/doc/resources/logo256.png (revision 13657) Property changes on: tags/1.2.7/doc/resources/logo256.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/resources/logo32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/logo32.png =================================================================== --- tags/1.2.7/doc/resources/logo32.png (nonexistent) +++ tags/1.2.7/doc/resources/logo32.png (revision 13657) Property changes on: tags/1.2.7/doc/resources/logo32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/resources/logo32.xpm =================================================================== --- tags/1.2.7/doc/resources/logo32.xpm (nonexistent) +++ tags/1.2.7/doc/resources/logo32.xpm (revision 13657) @@ -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/1.2.7/doc/resources/logo64.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/logo64.png =================================================================== --- tags/1.2.7/doc/resources/logo64.png (nonexistent) +++ tags/1.2.7/doc/resources/logo64.png (revision 13657) Property changes on: tags/1.2.7/doc/resources/logo64.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/resources/logo64.xpm =================================================================== --- tags/1.2.7/doc/resources/logo64.xpm (nonexistent) +++ tags/1.2.7/doc/resources/logo64.xpm (revision 13657) @@ -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/1.2.7/doc/resources/logo_made_with.pcb =================================================================== --- tags/1.2.7/doc/resources/logo_made_with.pcb (nonexistent) +++ tags/1.2.7/doc/resources/logo_made_with.pcb (revision 13657) @@ -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/1.2.7/doc/resources/screenshot.jpg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/resources/screenshot.jpg =================================================================== --- tags/1.2.7/doc/resources/screenshot.jpg (nonexistent) +++ tags/1.2.7/doc/resources/screenshot.jpg (revision 13657) Property changes on: tags/1.2.7/doc/resources/screenshot.jpg ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/security/bug1.html =================================================================== --- tags/1.2.7/doc/security/bug1.html (nonexistent) +++ tags/1.2.7/doc/security/bug1.html (revision 13657) @@ -0,0 +1,69 @@ + + + + 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 +
            • last stable release, patched: 1.2.5b +
            • old stable release, 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/1.2.7/doc/support.html =================================================================== --- tags/1.2.7/doc/support.html (nonexistent) +++ tags/1.2.7/doc/support.html (revision 13657) @@ -0,0 +1,53 @@ + + + + pcb-rnd - news + + + + + + + + + + +
            Main + News + Doc + Support + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +
            + +

            pcb-rnd support

            + +

            Get support

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

            +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. + +

            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/1.2.7/doc/tutorials/7805/7805.pcb =================================================================== --- tags/1.2.7/doc/tutorials/7805/7805.pcb (nonexistent) +++ tags/1.2.7/doc/tutorials/7805/7805.pcb (revision 13657) @@ -0,0 +1,994 @@ +# 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"] + +Symbol[' ' 457200nm] +( +) +Symbol['!' 304800nm] +( + SymbolLine[0 1143000nm 0 1270000nm 203200nm] + SymbolLine[0 254000nm 0 889000nm 203200nm] +) +Symbol['"' 304800nm] +( + SymbolLine[0 254000nm 0 508000nm 203200nm] + SymbolLine[254000nm 254000nm 254000nm 508000nm 203200nm] +) +Symbol['#' 304800nm] +( + SymbolLine[0 889000nm 508000nm 889000nm 203200nm] + SymbolLine[0 635000nm 508000nm 635000nm 203200nm] + SymbolLine[381000nm 508000nm 381000nm 1016000nm 203200nm] + SymbolLine[127000nm 508000nm 127000nm 1016000nm 203200nm] +) +Symbol['$' 304800nm] +( + SymbolLine[381000nm 381000nm 508000nm 508000nm 203200nm] + SymbolLine[127000nm 381000nm 381000nm 381000nm 203200nm] + SymbolLine[0 508000nm 127000nm 381000nm 203200nm] + SymbolLine[0 508000nm 0 635000nm 203200nm] + SymbolLine[0 635000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 508000nm 1016000nm 203200nm] + SymbolLine[381000nm 1143000nm 508000nm 1016000nm 203200nm] + SymbolLine[127000nm 1143000nm 381000nm 1143000nm 203200nm] + SymbolLine[0 1016000nm 127000nm 1143000nm 203200nm] + SymbolLine[254000nm 254000nm 254000nm 1270000nm 203200nm] +) +Symbol['%' 304800nm] +( + SymbolLine[0 381000nm 0 508000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 254000nm 254000nm 203200nm] + SymbolLine[254000nm 254000nm 381000nm 381000nm 203200nm] + SymbolLine[381000nm 381000nm 381000nm 508000nm 203200nm] + SymbolLine[254000nm 635000nm 381000nm 508000nm 203200nm] + SymbolLine[127000nm 635000nm 254000nm 635000nm 203200nm] + SymbolLine[0 508000nm 127000nm 635000nm 203200nm] + SymbolLine[0 1270000nm 1016000nm 254000nm 203200nm] + SymbolLine[889000nm 1270000nm 1016000nm 1143000nm 203200nm] + SymbolLine[1016000nm 1016000nm 1016000nm 1143000nm 203200nm] + SymbolLine[889000nm 889000nm 1016000nm 1016000nm 203200nm] + SymbolLine[762000nm 889000nm 889000nm 889000nm 203200nm] + SymbolLine[635000nm 1016000nm 762000nm 889000nm 203200nm] + SymbolLine[635000nm 1016000nm 635000nm 1143000nm 203200nm] + SymbolLine[635000nm 1143000nm 762000nm 1270000nm 203200nm] + SymbolLine[762000nm 1270000nm 889000nm 1270000nm 203200nm] +) +Symbol['&' 304800nm] +( + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 381000nm 0 635000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 889000nm 381000nm 508000nm 203200nm] + SymbolLine[127000nm 1270000nm 254000nm 1270000nm 203200nm] + SymbolLine[254000nm 1270000nm 508000nm 1016000nm 203200nm] + SymbolLine[0 635000nm 635000nm 1270000nm 203200nm] + SymbolLine[127000nm 254000nm 254000nm 254000nm 203200nm] + SymbolLine[254000nm 254000nm 381000nm 381000nm 203200nm] + SymbolLine[381000nm 381000nm 381000nm 508000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] +) +Symbol[''' 304800nm] +( + SymbolLine[0 508000nm 254000nm 254000nm 203200nm] +) +Symbol['(' 304800nm] +( + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 381000nm 0 1143000nm 203200nm] +) +Symbol[')' 304800nm] +( + SymbolLine[0 254000nm 127000nm 381000nm 203200nm] + SymbolLine[127000nm 381000nm 127000nm 1143000nm 203200nm] + SymbolLine[0 1270000nm 127000nm 1143000nm 203200nm] +) +Symbol['*' 304800nm] +( + SymbolLine[0 508000nm 508000nm 1016000nm 203200nm] + SymbolLine[0 1016000nm 508000nm 508000nm 203200nm] + SymbolLine[0 762000nm 508000nm 762000nm 203200nm] + SymbolLine[254000nm 508000nm 254000nm 1016000nm 203200nm] +) +Symbol['+' 304800nm] +( + SymbolLine[0 762000nm 508000nm 762000nm 203200nm] + SymbolLine[254000nm 508000nm 254000nm 1016000nm 203200nm] +) +Symbol[',' 304800nm] +( + SymbolLine[0 1524000nm 254000nm 1270000nm 203200nm] +) +Symbol['-' 304800nm] +( + SymbolLine[0 762000nm 508000nm 762000nm 203200nm] +) +Symbol['.' 304800nm] +( + SymbolLine[0 1270000nm 127000nm 1270000nm 203200nm] +) +Symbol['/' 304800nm] +( + SymbolLine[0 1143000nm 762000nm 381000nm 203200nm] +) +Symbol['0' 304800nm] +( + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 381000nm 0 1143000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1016000nm 508000nm 508000nm 203200nm] +) +Symbol['1' 304800nm] +( + SymbolLine[0 457200nm 203200nm 254000nm 203200nm] + SymbolLine[203200nm 254000nm 203200nm 1270000nm 203200nm] + SymbolLine[0 1270000nm 381000nm 1270000nm 203200nm] +) +Symbol['2' 304800nm] +( + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 508000nm 254000nm 203200nm] + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[635000nm 381000nm 635000nm 635000nm 203200nm] + SymbolLine[0 1270000nm 635000nm 635000nm 203200nm] + SymbolLine[0 1270000nm 635000nm 1270000nm 203200nm] +) +Symbol['3' 304800nm] +( + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 711200nm 381000nm 711200nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 584200nm 203200nm] + SymbolLine[508000nm 838200nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 838200nm 381000nm 711200nm 203200nm] + SymbolLine[508000nm 584200nm 381000nm 711200nm 203200nm] +) +Symbol['4' 304800nm] +( + SymbolLine[0 889000nm 508000nm 254000nm 203200nm] + SymbolLine[0 889000nm 635000nm 889000nm 203200nm] + SymbolLine[508000nm 254000nm 508000nm 1270000nm 203200nm] +) +Symbol['5' 304800nm] +( + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[0 254000nm 0 762000nm 203200nm] + SymbolLine[0 762000nm 127000nm 635000nm 203200nm] + SymbolLine[127000nm 635000nm 381000nm 635000nm 203200nm] + SymbolLine[381000nm 635000nm 508000nm 762000nm 203200nm] + SymbolLine[508000nm 762000nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['6' 304800nm] +( + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 381000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[381000nm 711200nm 508000nm 838200nm 203200nm] + SymbolLine[0 711200nm 381000nm 711200nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 838200nm 508000nm 1143000nm 203200nm] +) +Symbol['7' 304800nm] +( + SymbolLine[127000nm 1270000nm 635000nm 254000nm 203200nm] + SymbolLine[0 254000nm 635000nm 254000nm 203200nm] +) +Symbol['8' 304800nm] +( + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 939800nm 0 1143000nm 203200nm] + SymbolLine[0 939800nm 177800nm 762000nm 203200nm] + SymbolLine[177800nm 762000nm 330200nm 762000nm 203200nm] + SymbolLine[330200nm 762000nm 508000nm 939800nm 203200nm] + SymbolLine[508000nm 939800nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 584200nm 177800nm 762000nm 203200nm] + SymbolLine[0 381000nm 0 584200nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 584200nm 203200nm] + SymbolLine[330200nm 762000nm 508000nm 584200nm 203200nm] +) +Symbol['9' 304800nm] +( + SymbolLine[127000nm 1270000nm 508000nm 762000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 762000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 381000nm 0 635000nm 203200nm] + SymbolLine[0 635000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] +) +Symbol[':' 304800nm] +( + SymbolLine[0 635000nm 127000nm 635000nm 203200nm] + SymbolLine[0 889000nm 127000nm 889000nm 203200nm] +) +Symbol[';' 304800nm] +( + SymbolLine[0 1270000nm 254000nm 1016000nm 203200nm] + SymbolLine[254000nm 635000nm 254000nm 762000nm 203200nm] +) +Symbol['<' 304800nm] +( + SymbolLine[0 762000nm 254000nm 508000nm 203200nm] + SymbolLine[0 762000nm 254000nm 1016000nm 203200nm] +) +Symbol['=' 304800nm] +( + SymbolLine[0 635000nm 508000nm 635000nm 203200nm] + SymbolLine[0 889000nm 508000nm 889000nm 203200nm] +) +Symbol['>' 304800nm] +( + SymbolLine[0 508000nm 254000nm 762000nm 203200nm] + SymbolLine[0 1016000nm 254000nm 762000nm 203200nm] +) +Symbol['?' 304800nm] +( + SymbolLine[254000nm 762000nm 254000nm 889000nm 203200nm] + SymbolLine[254000nm 1143000nm 254000nm 1270000nm 203200nm] + SymbolLine[0 381000nm 0 508000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 508000nm 203200nm] + SymbolLine[254000nm 762000nm 508000nm 508000nm 203200nm] +) +Symbol['@' 304800nm] +( + SymbolLine[0 254000nm 0 1016000nm 203200nm] + SymbolLine[0 1016000nm 254000nm 1270000nm 203200nm] + SymbolLine[254000nm 1270000nm 1016000nm 1270000nm 203200nm] + SymbolLine[1270000nm 889000nm 1270000nm 254000nm 203200nm] + SymbolLine[1270000nm 254000nm 1016000nm 0 203200nm] + SymbolLine[1016000nm 0 254000nm 0 203200nm] + SymbolLine[254000nm 0 0 254000nm 203200nm] + SymbolLine[381000nm 508000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 762000nm 889000nm 203200nm] + SymbolLine[762000nm 889000nm 889000nm 762000nm 203200nm] + SymbolLine[889000nm 762000nm 1016000nm 889000nm 203200nm] + SymbolLine[889000nm 762000nm 889000nm 381000nm 203200nm] + SymbolLine[889000nm 508000nm 762000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 762000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 381000nm 508000nm 203200nm] + SymbolLine[1016000nm 889000nm 1270000nm 889000nm 203200nm] +) +Symbol['A' 304800nm] +( + SymbolLine[0 508000nm 0 1270000nm 203200nm] + SymbolLine[0 508000nm 177800nm 254000nm 203200nm] + SymbolLine[177800nm 254000nm 457200nm 254000nm 203200nm] + SymbolLine[457200nm 254000nm 635000nm 508000nm 203200nm] + SymbolLine[635000nm 508000nm 635000nm 1270000nm 203200nm] + SymbolLine[0 762000nm 635000nm 762000nm 203200nm] +) +Symbol['B' 304800nm] +( + SymbolLine[0 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1143000nm 203200nm] + SymbolLine[635000nm 838200nm 635000nm 1143000nm 203200nm] + SymbolLine[508000nm 711200nm 635000nm 838200nm 203200nm] + SymbolLine[127000nm 711200nm 508000nm 711200nm 203200nm] + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[635000nm 381000nm 635000nm 584200nm 203200nm] + SymbolLine[508000nm 711200nm 635000nm 584200nm 203200nm] +) +Symbol['C' 304800nm] +( + SymbolLine[177800nm 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[0 1092200nm 177800nm 1270000nm 203200nm] + SymbolLine[0 431800nm 0 1092200nm 203200nm] + SymbolLine[0 431800nm 177800nm 254000nm 203200nm] + SymbolLine[177800nm 254000nm 508000nm 254000nm 203200nm] +) +Symbol['D' 304800nm] +( + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[457200nm 254000nm 635000nm 431800nm 203200nm] + SymbolLine[635000nm 431800nm 635000nm 1092200nm 203200nm] + SymbolLine[457200nm 1270000nm 635000nm 1092200nm 203200nm] + SymbolLine[0 1270000nm 457200nm 1270000nm 203200nm] + SymbolLine[0 254000nm 457200nm 254000nm 203200nm] +) +Symbol['E' 304800nm] +( + SymbolLine[0 711200nm 381000nm 711200nm 203200nm] + SymbolLine[0 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] +) +Symbol['F' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[0 711200nm 381000nm 711200nm 203200nm] +) +Symbol['G' 304800nm] +( + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[127000nm 254000nm 508000nm 254000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 381000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1143000nm 203200nm] + SymbolLine[635000nm 889000nm 635000nm 1143000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 889000nm 203200nm] + SymbolLine[254000nm 762000nm 508000nm 762000nm 203200nm] +) +Symbol['H' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[635000nm 254000nm 635000nm 1270000nm 203200nm] + SymbolLine[0 762000nm 635000nm 762000nm 203200nm] +) +Symbol['I' 304800nm] +( + SymbolLine[0 254000nm 254000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 1270000nm 254000nm 1270000nm 203200nm] +) +Symbol['J' 304800nm] +( + SymbolLine[177800nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 381000nm 1143000nm 203200nm] + SymbolLine[254000nm 1270000nm 381000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 254000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 0 1016000nm 203200nm] +) +Symbol['K' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 762000nm 508000nm 254000nm 203200nm] + SymbolLine[0 762000nm 508000nm 1270000nm 203200nm] +) +Symbol['L' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 1270000nm 508000nm 1270000nm 203200nm] +) +Symbol['M' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 254000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 762000nm 254000nm 203200nm] + SymbolLine[762000nm 254000nm 762000nm 1270000nm 203200nm] +) +Symbol['N' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 254000nm 635000nm 1270000nm 203200nm] + SymbolLine[635000nm 254000nm 635000nm 1270000nm 203200nm] +) +Symbol['O' 304800nm] +( + SymbolLine[0 381000nm 0 1143000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['P' 304800nm] +( + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[635000nm 381000nm 635000nm 635000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 635000nm 203200nm] + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] +) +Symbol['Q' 304800nm] +( + SymbolLine[0 381000nm 0 1143000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[381000nm 254000nm 508000nm 381000nm 203200nm] + SymbolLine[508000nm 381000nm 508000nm 1016000nm 203200nm] + SymbolLine[254000nm 1270000nm 508000nm 1016000nm 203200nm] + SymbolLine[127000nm 1270000nm 254000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[254000nm 889000nm 508000nm 1270000nm 203200nm] +) +Symbol['R' 304800nm] +( + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[635000nm 381000nm 635000nm 635000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 635000nm 203200nm] + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[330200nm 762000nm 635000nm 1270000nm 203200nm] +) +Symbol['S' 304800nm] +( + SymbolLine[508000nm 254000nm 635000nm 381000nm 203200nm] + SymbolLine[127000nm 254000nm 508000nm 254000nm 203200nm] + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[0 381000nm 0 635000nm 203200nm] + SymbolLine[0 635000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 889000nm 203200nm] + SymbolLine[635000nm 889000nm 635000nm 1143000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['T' 304800nm] +( + SymbolLine[0 254000nm 508000nm 254000nm 203200nm] + SymbolLine[254000nm 254000nm 254000nm 1270000nm 203200nm] +) +Symbol['U' 304800nm] +( + SymbolLine[0 254000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 254000nm 508000nm 1143000nm 203200nm] +) +Symbol['V' 304800nm] +( + SymbolLine[0 254000nm 254000nm 1270000nm 203200nm] + SymbolLine[254000nm 1270000nm 508000nm 254000nm 203200nm] +) +Symbol['W' 304800nm] +( + SymbolLine[0 254000nm 0 762000nm 203200nm] + SymbolLine[0 762000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 635000nm 1270000nm 203200nm] + SymbolLine[635000nm 1270000nm 762000nm 762000nm 203200nm] + SymbolLine[762000nm 762000nm 762000nm 254000nm 203200nm] +) +Symbol['X' 304800nm] +( + SymbolLine[0 1270000nm 635000nm 254000nm 203200nm] + SymbolLine[0 254000nm 635000nm 1270000nm 203200nm] +) +Symbol['Y' 304800nm] +( + SymbolLine[0 254000nm 254000nm 762000nm 203200nm] + SymbolLine[254000nm 762000nm 508000nm 254000nm 203200nm] + SymbolLine[254000nm 762000nm 254000nm 1270000nm 203200nm] +) +Symbol['Z' 304800nm] +( + SymbolLine[0 254000nm 635000nm 254000nm 203200nm] + SymbolLine[0 1270000nm 635000nm 254000nm 203200nm] + SymbolLine[0 1270000nm 635000nm 1270000nm 203200nm] +) +Symbol['[' 304800nm] +( + SymbolLine[0 254000nm 127000nm 254000nm 203200nm] + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 1270000nm 127000nm 1270000nm 203200nm] +) +Symbol['\' 304800nm] +( + SymbolLine[0 381000nm 762000nm 1143000nm 203200nm] +) +Symbol[']' 304800nm] +( + SymbolLine[0 254000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 127000nm 1270000nm 203200nm] + SymbolLine[0 1270000nm 127000nm 1270000nm 203200nm] +) +Symbol['^' 304800nm] +( + SymbolLine[0 381000nm 127000nm 254000nm 203200nm] + SymbolLine[127000nm 254000nm 254000nm 381000nm 203200nm] +) +Symbol['_' 304800nm] +( + SymbolLine[0 1270000nm 508000nm 1270000nm 203200nm] +) +Symbol['a' 304800nm] +( + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[508000nm 762000nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 1143000nm 635000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] +) +Symbol['b' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 889000nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] +) +Symbol['c' 304800nm] +( + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 508000nm 1270000nm 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] +) +Symbol['e' 304800nm] +( + SymbolLine[127000nm 1270000nm 508000nm 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] + SymbolLine[0 1016000nm 508000nm 1016000nm 203200nm] + SymbolLine[508000nm 1016000nm 508000nm 889000nm 203200nm] +) +Symbol['f' 254000nm] +( + SymbolLine[127000nm 381000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 381000nm 254000nm 254000nm 203200nm] + SymbolLine[254000nm 254000nm 381000nm 254000nm 203200nm] + SymbolLine[0 762000nm 254000nm 762000nm 203200nm] +) +Symbol['g' 304800nm] +( + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[0 1524000nm 127000nm 1651000nm 203200nm] + SymbolLine[127000nm 1651000nm 381000nm 1651000nm 203200nm] + SymbolLine[381000nm 1651000nm 508000nm 1524000nm 203200nm] + SymbolLine[508000nm 762000nm 508000nm 1524000nm 203200nm] +) +Symbol['h' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 508000nm 1270000nm 203200nm] +) +Symbol['i' 254000nm] +( + SymbolLine[0 508000nm 0 533400nm 254000nm] + SymbolLine[0 889000nm 0 1270000nm 203200nm] +) +Symbol['j' 254000nm] +( + SymbolLine[127000nm 508000nm 127000nm 533400nm 254000nm] + SymbolLine[127000nm 889000nm 127000nm 1524000nm 203200nm] + SymbolLine[0 1651000nm 127000nm 1524000nm 203200nm] +) +Symbol['k' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] + SymbolLine[0 889000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 889000nm 254000nm 635000nm 203200nm] +) +Symbol['l' 254000nm] +( + SymbolLine[0 254000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['m' 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[508000nm 889000nm 635000nm 762000nm 203200nm] + SymbolLine[635000nm 762000nm 762000nm 762000nm 203200nm] + SymbolLine[762000nm 762000nm 889000nm 889000nm 203200nm] + SymbolLine[889000nm 889000nm 889000nm 1270000nm 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['o' 304800nm] +( + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 508000nm 1143000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['p' 304800nm] +( + SymbolLine[127000nm 889000nm 127000nm 1651000nm 203200nm] + SymbolLine[0 762000nm 127000nm 889000nm 203200nm] + SymbolLine[127000nm 889000nm 254000nm 762000nm 203200nm] + SymbolLine[254000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 889000nm 203200nm] + SymbolLine[635000nm 889000nm 635000nm 1143000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1143000nm 203200nm] + SymbolLine[254000nm 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[127000nm 1143000nm 254000nm 1270000nm 203200nm] +) +Symbol['q' 304800nm] +( + SymbolLine[508000nm 889000nm 508000nm 1651000nm 203200nm] + SymbolLine[381000nm 762000nm 508000nm 889000nm 203200nm] + SymbolLine[127000nm 762000nm 381000nm 762000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[0 889000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] +) +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['s' 304800nm] +( + SymbolLine[127000nm 1270000nm 508000nm 1270000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1143000nm 203200nm] + SymbolLine[508000nm 1016000nm 635000nm 1143000nm 203200nm] + SymbolLine[127000nm 1016000nm 508000nm 1016000nm 203200nm] + SymbolLine[0 889000nm 127000nm 1016000nm 203200nm] + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 508000nm 762000nm 203200nm] + SymbolLine[508000nm 762000nm 635000nm 889000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] +) +Symbol['t' 254000nm] +( + SymbolLine[127000nm 254000nm 127000nm 1143000nm 203200nm] + SymbolLine[127000nm 1143000nm 254000nm 1270000nm 203200nm] + SymbolLine[0 635000nm 254000nm 635000nm 203200nm] +) +Symbol['u' 304800nm] +( + SymbolLine[0 762000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] + SymbolLine[508000nm 762000nm 508000nm 1143000nm 203200nm] +) +Symbol['v' 304800nm] +( + SymbolLine[0 762000nm 254000nm 1270000nm 203200nm] + SymbolLine[508000nm 762000nm 254000nm 1270000nm 203200nm] +) +Symbol['w' 304800nm] +( + SymbolLine[0 762000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[127000nm 1270000nm 254000nm 1270000nm 203200nm] + SymbolLine[254000nm 1270000nm 381000nm 1143000nm 203200nm] + SymbolLine[381000nm 762000nm 381000nm 1143000nm 203200nm] + SymbolLine[381000nm 1143000nm 508000nm 1270000nm 203200nm] + SymbolLine[508000nm 1270000nm 635000nm 1270000nm 203200nm] + SymbolLine[635000nm 1270000nm 762000nm 1143000nm 203200nm] + SymbolLine[762000nm 762000nm 762000nm 1143000nm 203200nm] +) +Symbol['x' 304800nm] +( + SymbolLine[0 762000nm 508000nm 1270000nm 203200nm] + SymbolLine[0 1270000nm 508000nm 762000nm 203200nm] +) +Symbol['y' 304800nm] +( + SymbolLine[0 762000nm 0 1143000nm 203200nm] + SymbolLine[0 1143000nm 127000nm 1270000nm 203200nm] + SymbolLine[508000nm 762000nm 508000nm 1524000nm 203200nm] + SymbolLine[381000nm 1651000nm 508000nm 1524000nm 203200nm] + SymbolLine[127000nm 1651000nm 381000nm 1651000nm 203200nm] + SymbolLine[0 1524000nm 127000nm 1651000nm 203200nm] + SymbolLine[127000nm 1270000nm 381000nm 1270000nm 203200nm] + SymbolLine[381000nm 1270000nm 508000nm 1143000nm 203200nm] +) +Symbol['z' 304800nm] +( + SymbolLine[0 762000nm 508000nm 762000nm 203200nm] + SymbolLine[0 1270000nm 508000nm 762000nm 203200nm] + SymbolLine[0 1270000nm 508000nm 1270000nm 203200nm] +) +Symbol['{' 304800nm] +( + SymbolLine[127000nm 381000nm 254000nm 254000nm 203200nm] + SymbolLine[127000nm 381000nm 127000nm 635000nm 203200nm] + SymbolLine[0 762000nm 127000nm 635000nm 203200nm] + SymbolLine[0 762000nm 127000nm 889000nm 203200nm] + SymbolLine[127000nm 889000nm 127000nm 1143000nm 203200nm] + SymbolLine[127000nm 1143000nm 254000nm 1270000nm 203200nm] +) +Symbol['|' 304800nm] +( + SymbolLine[0 254000nm 0 1270000nm 203200nm] +) +Symbol['}' 304800nm] +( + SymbolLine[0 254000nm 127000nm 381000nm 203200nm] + SymbolLine[127000nm 381000nm 127000nm 635000nm 203200nm] + SymbolLine[127000nm 635000nm 254000nm 762000nm 203200nm] + SymbolLine[127000nm 889000nm 254000nm 762000nm 203200nm] + SymbolLine[127000nm 889000nm 127000nm 1143000nm 203200nm] + SymbolLine[0 1270000nm 127000nm 1143000nm 203200nm] +) +Symbol['~' 304800nm] +( + SymbolLine[0 889000nm 127000nm 762000nm 203200nm] + SymbolLine[127000nm 762000nm 254000nm 762000nm 203200nm] + SymbolLine[254000nm 762000nm 381000nm 889000nm 203200nm] + SymbolLine[381000nm 889000nm 508000nm 889000nm 203200nm] + SymbolLine[508000nm 889000nm 635000nm 762000nm 203200nm] +) +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/1.2.7/doc/tutorials/7805/7805.sch =================================================================== --- tags/1.2.7/doc/tutorials/7805/7805.sch (nonexistent) +++ tags/1.2.7/doc/tutorials/7805/7805.sch (revision 13657) @@ -0,0 +1,88 @@ +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 +} +C 21100 57200 1 0 1 connector3-2.sym +{ +T 20400 58900 5 10 1 1 0 0 1 +refdes=CONN1 +T 20800 58850 5 10 0 0 0 6 1 +device=CONNECTOR_3 +T 20800 59050 5 10 0 0 0 6 1 +footprint=connector(3,1) +} +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 +T 21200 57500 9 10 1 0 0 0 1 +key +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=CONN2 +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(2,1) +} +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=C1 +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=47uF +} +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=C2 +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=0805 +} +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=C3 +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=0805 +} +N 25000 58000 25000 58400 4 +C 24900 56400 1 0 0 gnd-1.sym +N 25000 56700 25000 57100 4 Index: tags/1.2.7/doc/tutorials/7805/Info.lht =================================================================== --- tags/1.2.7/doc/tutorials/7805/Info.lht (nonexistent) +++ tags/1.2.7/doc/tutorials/7805/Info.lht (revision 13657) @@ -0,0 +1,13 @@ +ha:pcb-rnd-tutorial { + level=10 + li:demonstrates { + gschem + gsch2pcb-rnd + make + } + short = 7805 module with connectors + long { + A 7805 based voltage source module to demonstrate a simple + gschem -> gsch2pcb-rnd -> pcb-rnd forward annotation chain. + } +} Index: tags/1.2.7/doc/tutorials/7805/Makefile =================================================================== --- tags/1.2.7/doc/tutorials/7805/Makefile (nonexistent) +++ tags/1.2.7/doc/tutorials/7805/Makefile (revision 13657) @@ -0,0 +1,5 @@ +7805.lht: 7805.sch + gsch2pcb-rnd -m import 7805.sch + +clean: + rm -f 7805.cmd Index: tags/1.2.7/doc/tutorials/7805/index.html =================================================================== --- tags/1.2.7/doc/tutorials/7805/index.html (nonexistent) +++ tags/1.2.7/doc/tutorials/7805/index.html (revision 13657) @@ -0,0 +1,96 @@ +

            Step 1: schematics

            +

            + The schematics is usually the single source of all logical information: + footprints, element 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. Start + gschem with an empty design and save it in the project directory. + Place the following symbols and edit/add these attributes: +

              +
            • 7805, footprint=TO220, refdes=U1 +
            • connector-3-2, footprint=connector(3,1), refdes=CONN1 +
            • connector-2-2, footprint=connector(2,1), refdes=CONN2 +
            • capacitor-2, fooptrint=rcy(200), value=47uF, refdes=C1 +
            • capacitor-1, fooptrint=0805, value=100nF, refdes=C2 +
            • capacitor-2, fooptrint=0805, value=100nF, refdes=C2 +
            • gnd-1 +
            +

            + Arrange and connect the pins as shown below. +

            + schematics +

            + Save the design as 7805.sch. +

            Step 2: build script

            +

            + We are going to use a Makefile in this example to demonstrate + how to automate certain steps. In a fully automated project all + data exchange between the various tools (schematics editor, pcb-rnd, + simulators, etc.) is done by scripts. Generating the documentation + and exporting various other output like gerbers are usually automated + the same way. (As an alternative, all these can be done manually, from + the GUI as well.) +

            + Create a new file called Makefile and edit it using your favorite text + editor to the following: +

            +7805.lht: 7805.sch
            +	gsch2pcb-rnd -m import 7805.sch
            +
            +clean:
            +	rm -f 7805.cmd
            +		
            +

            + The first rule calls the forward annotation utility, gsch2pcb-rnd to + create a forward annotation command file called 7805.cmd when the + schematics file is newer than the layout file (7805.lht). The second + rule removes such a command file to make the directory clean of + auto-generated temporary files. + +

            Step 3: Create the initial board

            +

            + The layout process usually starts when there's at least a partially + finished schematics is available. The most common workflow is that + changes and improvements in the schematics are forward annotated to + the layout. +

            + Start pcb-rnd. This will load the system-installed template board + as a new, empty design. Save it in the project directory as 7805.lht. +

            + Start a shell (but don't close pcb-rnd); in the project directory, + type make. This will create 7805.cmd that contains a pcb-rnd + action script that can sync a board to the information extracted from + the schematics. +

            + Back in pcb-rnd, type ":ExecuteFile(7805.cmd)" and press enter. The colon + will open the CLI entry where the ExecuteFile(filename) is an action that + will load the file named and execute each line as an action. +

            + At the end of the process, the layout should have all footprints. Press + 'o' and the logical connections will show up as a "rats nest". + +

            Step 4: Lay out the board

            +

            + Move the elements around. Pressing 'o' after some moves will re-optimize + the rats. As rats nest gets simpler and simpler, this can help choosing + the best placement. All components started out on the component (top) side. + Hover the mouse over the 0805 capacitors and press 'b' - this will send + them to the solder side. +

            + After the placement, pick the solder layer to draw on and use the line tool + to draw the traces. Change the style to 'Power' or 'Fat' to get wider + traces. Press 'o' after drawing a few connections. When only the ground + network is left, use the rectangle tool to draw a large polygon on the + solder-gnd layer. Use the thermal tool to connect pins to the ground polygon. + The thermal tool does not work on SMD pads, they need to be connected using + lines. +

            + When everything is connected, pressing 'o' will remove the last rat line. + The message log window also shows how many rats are remaining when 'o' + is pressed. The message log can be opened using the + Window/Message Log menu. + +

            Step 5: updates

            +

            Index: tags/1.2.7/doc/tutorials/pnp-origin/index.html =================================================================== --- tags/1.2.7/doc/tutorials/pnp-origin/index.html (nonexistent) +++ tags/1.2.7/doc/tutorials/pnp-origin/index.html (revision 13657) @@ -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 element 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/1.2.7/doc/tutorials/pnp-origin/orig_impl.lht =================================================================== --- tags/1.2.7/doc/tutorials/pnp-origin/orig_impl.lht (nonexistent) +++ tags/1.2.7/doc/tutorials/pnp-origin/orig_impl.lht (revision 13657) @@ -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/1.2.7/doc/tutorials/pnp-origin/orig_round.lht =================================================================== --- tags/1.2.7/doc/tutorials/pnp-origin/orig_round.lht (nonexistent) +++ tags/1.2.7/doc/tutorials/pnp-origin/orig_round.lht (revision 13657) @@ -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/1.2.7/doc/tutorials/pnp-origin/orig_sq.lht =================================================================== --- tags/1.2.7/doc/tutorials/pnp-origin/orig_sq.lht (nonexistent) +++ tags/1.2.7/doc/tutorials/pnp-origin/orig_sq.lht (revision 13657) @@ -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/1.2.7/doc/user/01_intro/Makefile =================================================================== --- tags/1.2.7/doc/user/01_intro/Makefile (nonexistent) +++ tags/1.2.7/doc/user/01_intro/Makefile (revision 13657) @@ -0,0 +1,2 @@ +flow.svg: src/flow.dot + dot -Tsvg src/flow.dot > flow.svg Index: tags/1.2.7/doc/user/01_intro/flow.svg =================================================================== --- tags/1.2.7/doc/user/01_intro/flow.svg (nonexistent) +++ tags/1.2.7/doc/user/01_intro/flow.svg (revision 13657) @@ -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/1.2.7/doc/user/01_intro/history.html =================================================================== --- tags/1.2.7/doc/user/01_intro/history.html (nonexistent) +++ tags/1.2.7/doc/user/01_intro/history.html (revision 13657) @@ -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/1.2.7/doc/user/01_intro/index.html =================================================================== --- tags/1.2.7/doc/user/01_intro/index.html (nonexistent) +++ tags/1.2.7/doc/user/01_intro/index.html (revision 13657) @@ -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. element 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/1.2.7/doc/user/01_intro/src/flow.dot =================================================================== --- tags/1.2.7/doc/user/01_intro/src/flow.dot (nonexistent) +++ tags/1.2.7/doc/user/01_intro/src/flow.dot (revision 13657) @@ -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/1.2.7/doc/user/02_model/index.html =================================================================== --- tags/1.2.7/doc/user/02_model/index.html (nonexistent) +++ tags/1.2.7/doc/user/02_model/index.html (revision 13657) @@ -0,0 +1,623 @@ + + + + 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 the outline layer. If the board is not rectangular, the +contour must be specified on the outline layer 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 +elementname-pinname, e.g. U4-7 means "pin number 7 in element 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 type. Types are: +

              +
            • copper for signal layers +
            • silk for silkscreen layers +
            • outline for the contour of the board and slots and cutouts +
            • mask for solder masks +
            • paste for solder paste +
            +

            +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 an outline +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 +
            outline no no no yes no +
            + +

            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 +
            + + +

            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) +
            • vias and pins, if they are not connected to the polygon by thermals +
            • pads +
            +

            +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 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. Via Objects

            +

            +A via is an electrically connected hole that connects copper rings to multiple +layers. Thermal relief styles are available to both pads and pins, and the shape +styles of a via are available to pins. Since a via hole always punches all layer +groups and applies the same ring style on any outside layer groups, blind or +buried vias and individually defined layer pad stacks (e.g. with changing ring +shape per layer) are not possible using the via object. +

            +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 +
            +

            +A variety of pin pad shapes are also available to the pcb-rnd user. The copper +annulus (ring) on the outside layer groups is selectable from a predefined set +of shapes that provide solderability or can be used to indicate a special pin. +Flags in the via object define the shape used. + +
            Via Annulus Shape Styles +
            Shape Appearance +
            ring (default) Ring via style +
            square Square via style +
            octagon Octagonal via style +
            asymmetric Asymmetric via style +
            + +

            2.4.6. Element Objects and Footprints

            + +

            +An element is an instance of a footprint that is already placed on the +board or loaded into a paste buffer. + +

            +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 element. The element 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 element +lands on a specific board layer; the refdes is rendered using the font in +the current board. + +

            +The footprint -> element instantiation is also a copy. Once the element +is created from a footprint, the element 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 elements. + +

            +In other words, a footprint is an abstract recipe, part of a +library, while an element is a land pattern already embedded in a +specific design and describes actual copper and silk. + +

            +Currently an element or footprint can contain the following objects: +

              +
            • pins - same as vias, but also have a pin number and pin name within the element; they affect all layers +
            • pads - short lines, usually with rectangle end cap; pads also have number and name; they affect the top or bottom copper layer only +
            • silk lines - on top or bottom silk layer +
            • silk arcs - on top or bottom silk layer +
            • silk text - limited: only one of refdes, element name and element value is displayed at the time +
            +

            +An element has the following properties: +

            + +
            Element Properties +
            element property description +
            name: refdes unique identifier, e.g. "C42" +
            name: value informal value, e.g. "15 pF" +
            name: description informal element or footprint description, e.g. "1206" +
            +

            +Extra object flags: +

            + +
            Element Flags +
            name description +
            ONSOLDER when set, the element is on the bottom side, else it's on the top side +
            NONETLIST when set, the element is not intended to be on the netlist; useful for elements that are not present on the schematics and are placed during the layout design +
            HIDENAME when set the name of the element is hidden +
            DISPLAYNAME when set the names of pins are shown +
            + +

            2.4.7. Pins of Elements

            + +A pin of an element is really a via, plus some metadata and capabilities: +
              +
            • pin name +
            • pin number +
            • the capability to act as a netlist terminal +
            + +Each element has its own list of pins. Pin rings can overlap (which will +make galvanic connection). There may be duplicate pin numbers and pin names. +Pin numbers are in the same namespace as pad numbers. + +A pin has the following properties: +

            + +
            Pin Properties +
            name description +
            name pin name, e.g. "base" +
            number pin name, e.g. 2 +
            intconn internal element connections (see section TODO) +
            + +Extra object flags: +

            + +
            Pin Element Flags +
            name description +
            via flags (extra flags listed for vias are applicable to pins too) +
            WARN the pin contributes to a short circuit ("orange mark") +
            + +

            2.4.8. Pads of Elements

            +

            +A pad is an smd pad of an element. It is modelled as a line segment, usually +with square cap - this makes the pad look like a rectangle. A pad has +the same metadata and capabilities as pins. Overlapping pads are supported. +A pad is always on either the top or the bottom copper layer group. +

            +A pad has the following properties: +

            + +
            Pad Properties +
            name description +
            name pin name, e.g. "base" +
            number pin name, e.g. 2 +
            intconn internal element connections (see section TODO) +
            + +Extra object flags: +

            + +
            Pad Object Flags +
            name description +
            via flags (extra flags listed for vias are applicable to pins too) +
            WARN the pin contributes to a short circuit ("orange mark") +
            EDGE2 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) +
            + +

            2.4.9. 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.9.1 Subcircuits as footprints
            +

            +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.9.2 Subcircuits as repetitive modules
            +

            +Compared to subcircuits as footprint, a repetitive module will not have +a refdes attribute and will not have terminals. + + +

            2.4.10. 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 +
            +

            +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 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. + + +

            2.4.11. 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.12. 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 element-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 element refdes are unique. If an element has multiple +instances of the same pin (or pad) number, the engine picks one randomly and +assumes there's an invisible, internal connection within the element. +

            +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: +pins can be swapped, element packages replaced using back annotation +actions. Such actions will keep a list of intended netlist and element +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/element changes as the new netlist import netlist matches +the intended (changed) netlist. + +

            2.5. 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 elemnts +
            Outline routing path Outline layer designed using standard pcb-rnd elemnts +
            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 +
            Index: tags/1.2.7/doc/user/02_model/obj_arc.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/obj_arc.png =================================================================== --- tags/1.2.7/doc/user/02_model/obj_arc.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/obj_arc.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/02_model/obj_line.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/obj_line.png =================================================================== --- tags/1.2.7/doc/user/02_model/obj_line.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/obj_line.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/02_model/objects_basic.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/objects_basic.png =================================================================== --- tags/1.2.7/doc/user/02_model/objects_basic.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/objects_basic.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/02_model/objects_complex.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/objects_complex.png =================================================================== --- tags/1.2.7/doc/user/02_model/objects_complex.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/objects_complex.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/02_model/src/Makefile =================================================================== --- tags/1.2.7/doc/user/02_model/src/Makefile (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/Makefile (revision 13657) @@ -0,0 +1,70 @@ +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 \ + via_ring_shape.png via_square_shape.png via_octagon_shape.png \ + via_asym_shape.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/1.2.7/doc/user/02_model/src/obj_arc.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/obj_arc.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/obj_arc.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/obj_line.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/obj_line.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/obj_line.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/objects_basic.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/objects_basic.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/objects_basic.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/objects_complex.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/objects_complex.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/objects_complex.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_asym_shape.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_asym_shape.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_asym_shape.lht (revision 13657) @@ -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.485mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.127 { + x=150.0mil; y=140.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=3 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.132 { + 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.123 { + string=Asymmetric; x=20.0mil; y=230.0mil; scale=80; 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 + 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 = 485.00 um + } + } + } +} Index: tags/1.2.7/doc/user/02_model/src/via_octagon_shape.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_octagon_shape.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_octagon_shape.lht (revision 13657) @@ -0,0 +1,269 @@ +ha:pcb-rnd-board-v2 { + + 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 = 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 = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.107 { + x=150.0mil; y=140.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=17 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + + li:objects { + ha:polygon.117 { + 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.118 { + string=Octagon; x=75.0mil; y=225.0mil; scale=80; 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 + 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 + } + } + } +} Index: tags/1.2.7/doc/user/02_model/src/via_ring_shape.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_ring_shape.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_ring_shape.lht (revision 13657) @@ -0,0 +1,268 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::loader}=geda/pcb - nanometer + {PCB::grid::unit}=mil + {PCB::conf::editor/buffer_number}=0 + {PCB::conf::editor/draw_grid}=true + {PCB::conf::editor/grid}=235.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.235mm + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.107 { + x=150.0mil; y=140.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.124 { + 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.119 { + string=Ring; x=110mil; y=5.95mm; scale=80; 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 + 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 = 235.00 um + } + } + } +} Index: tags/1.2.7/doc/user/02_model/src/via_square_shape.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_square_shape.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_square_shape.lht (revision 13657) @@ -0,0 +1,266 @@ +ha:pcb-rnd-board-v2 { + + ha:attributes { + {PCB::grid::unit}=mil + {PCB::conf::editor/draw_grid}=false + } + + 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 = 25.0mil + offs_x = 0.0 + offs_y = 0.0 + } + } + + ha:data { + + li:objects { + ha:via.132 { + x=150.0mil; y=140.0mil; hole=47.24mil; mask=0.0; thickness=137.8mil; clearance=50.0mil; + ha:flags { + via=1 + square=1 + shape=1 + } + } + } + li:layers { + + ha:component { + lid=0 + group=3 + ha:combining { } + visible=1 + + li:objects { + ha:polygon.126 { + 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.132 { + string=Square; x=75.0mil; y=230.0mil; scale=85; 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 + 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 + } + } + } +} Index: tags/1.2.7/doc/user/02_model/src/via_therm_noconn.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_noconn.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_noconn.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_therm_round_x45.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_round_x45.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_round_x45.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_therm_round_x90.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_round_x90.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_round_x90.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_therm_sharp_x45.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_sharp_x45.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_sharp_x45.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_therm_sharp_x90.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_sharp_x90.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_sharp_x90.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/src/via_therm_solid.lht =================================================================== --- tags/1.2.7/doc/user/02_model/src/via_therm_solid.lht (nonexistent) +++ tags/1.2.7/doc/user/02_model/src/via_therm_solid.lht (revision 13657) @@ -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/1.2.7/doc/user/02_model/via_asym_shape.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_asym_shape.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_asym_shape.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_asym_shape.png (revision 13657) Property changes on: tags/1.2.7/doc/user/02_model/via_asym_shape.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/02_model/via_octagon_shape.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_octagon_shape.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_octagon_shape.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_octagon_shape.png (revision 13657) Property changes on: tags/1.2.7/doc/user/02_model/via_octagon_shape.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/02_model/via_ring_shape.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_ring_shape.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_ring_shape.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_ring_shape.png (revision 13657) Property changes on: tags/1.2.7/doc/user/02_model/via_ring_shape.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/02_model/via_square_shape.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_square_shape.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_square_shape.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_square_shape.png (revision 13657) Property changes on: tags/1.2.7/doc/user/02_model/via_square_shape.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/02_model/via_therm_noconn.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_therm_noconn.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_noconn.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_noconn.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/02_model/via_therm_round_x45.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_round_x45.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_round_x45.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/02_model/via_therm_round_x90.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_round_x90.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_round_x90.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/02_model/via_therm_sharp_x45.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_sharp_x45.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_sharp_x45.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/02_model/via_therm_sharp_x90.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_sharp_x90.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_sharp_x90.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/02_model/via_therm_solid.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/02_model/via_therm_solid.png =================================================================== --- tags/1.2.7/doc/user/02_model/via_therm_solid.png (nonexistent) +++ tags/1.2.7/doc/user/02_model/via_therm_solid.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/03_data/index.html =================================================================== --- tags/1.2.7/doc/user/03_data/index.html (nonexistent) +++ tags/1.2.7/doc/user/03_data/index.html (revision 13657) @@ -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 element/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/1.2.7/doc/user/04_invoc/index.html =================================================================== --- tags/1.2.7/doc/user/04_invoc/index.html (nonexistent) +++ tags/1.2.7/doc/user/04_invoc/index.html (revision 13657) @@ -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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_main.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_main.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_main.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_menus.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_workops.png =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/05_ui/01_gtk/index.html =================================================================== --- tags/1.2.7/doc/user/05_ui/01_gtk/index.html (nonexistent) +++ tags/1.2.7/doc/user/05_ui/01_gtk/index.html (revision 13657) @@ -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/1.2.7/doc/user/05_ui/02_cli/index.html =================================================================== --- tags/1.2.7/doc/user/05_ui/02_cli/index.html (nonexistent) +++ tags/1.2.7/doc/user/05_ui/02_cli/index.html (revision 13657) @@ -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/1.2.7/doc/user/05_ui/05_batch/index.html =================================================================== --- tags/1.2.7/doc/user/05_ui/05_batch/index.html (nonexistent) +++ tags/1.2.7/doc/user/05_ui/05_batch/index.html (revision 13657) @@ -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/1.2.7/doc/user/05_ui/index.html =================================================================== --- tags/1.2.7/doc/user/05_ui/index.html (nonexistent) +++ tags/1.2.7/doc/user/05_ui/index.html (revision 13657) @@ -0,0 +1,28 @@ + + + + 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/1.2.7/doc/user/06_feature/acompnet/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/acompnet/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/acompnet/index.html (revision 13657) @@ -0,0 +1,17 @@ + + + + pcb-rnd user manual + + + + +

            Acompnet plugin

            +

            +Acompnet was originally concieved as a limited autorouter and layout assistant. It is disabled by default. +Issues: +

            +

          • Acompnet is a work in progress, incomplete, and disabled by default in the +pcb-rnd builds. + + Index: tags/1.2.7/doc/user/06_feature/autocrop/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/autocrop/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/autocrop/index.html (revision 13657) @@ -0,0 +1,33 @@ + + + + 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 calcaulate for complex layouts. +
          • Autocrop was originally written for the old geda pcb with undo for board size +
          • Edge clearance is fixed at 5*line spacing + + + + Index: tags/1.2.7/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/1.2.7/doc/user/06_feature/distalign/align_mixed_parts_x.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/align_mixed_parts_x.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/align_mixed_parts_x.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/06_feature/distalign/align_parts_y.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/align_parts_y.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/align_parts_y.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/06_feature/distalign/distribute_parts_x.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/distribute_parts_x.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/distribute_parts_x.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/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/1.2.7/doc/user/06_feature/distalign/distribute_y_gaps.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/distribute_y_gaps.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/distribute_y_gaps.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distalign/import_parts.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/distalign/import_parts.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/import_parts.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/import_parts.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distalign/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/index.html (revision 13657) @@ -0,0 +1,70 @@ + + + + pcb-rnd user manual + + + + +

            Distalign plugin

            +
            +Two actions for aligning and distributing elements 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 elements along the X or Y axis, relative to user selected reference points (like specific element edges, their centers, or marks) +

            +

            +distribute() distributes selected elements evenly between the first or last element 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 +
            +
            + + + + Index: tags/1.2.7/doc/user/06_feature/distalign/result.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/distalign/result.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distalign/result.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distalign/result.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distaligntext/distaligntext_1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_1.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_1.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_1.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distaligntext/distaligntext_2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_2.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_2.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_2.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distaligntext/distaligntext_3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_3.png =================================================================== --- tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_3.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distaligntext/distaligntext_3.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/distaligntext/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/distaligntext/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/distaligntext/index.html (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/Makefile =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/Makefile (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/Makefile (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/Post.html =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/Post.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/Post.html (revision 13657) @@ -0,0 +1,4 @@ +
            autorun all the above except miter; run them multiple times until there's no more change possible     +
            + + Index: tags/1.2.7/doc/user/06_feature/djopt/Pre.html =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/Pre.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/Pre.html (revision 13657) @@ -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. + + +" + print "" + } + s="" + d="" +} + +BEGIN { + q="\"" +# first line of input is the version + getline pcb_rnd_ver + getline pcb_rnd_rev + print "" + print "" + print "" + print " pcb-rnd user manual " + print "" + print "" + print "" + print "" + print "

            " + print "

            Pcb-rnd Action Reference

            " + print "
            argument name description example in example out after 1st iteration Index: tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/debumpify.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/debumpify.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/debumpify.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/debumpify.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/debumpify.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/debumpify.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/debumpify.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/debumpify.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/debumpify.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/debumpify.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/debumpify.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/debumpify.txt (revision 13657) @@ -0,0 +1,2 @@ +Looks for U-shaped traces (with 90 degree corners) that can be shortened +or eliminated. Index: tags/1.2.7/doc/user/06_feature/djopt/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/index.html (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/miter.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/miter.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/miter.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/miter.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/miter.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/miter.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/miter.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/miter.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/miter.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/miter.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/miter.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/miter.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/miter.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/miter.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/miter.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/miter.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/miter.txt (revision 13657) @@ -0,0 +1,2 @@ +Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. Index: tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/orthopull.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/orthopull.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/orthopull.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/orthopull.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/orthopull.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/orthopull.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/orthopull.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/orthopull.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/orthopull.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/orthopull.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/orthopull.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/orthopull.txt (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/unjaggy.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/unjaggy.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/unjaggy.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/unjaggy.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/unjaggy.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/unjaggy.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/unjaggy.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/unjaggy.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/unjaggy.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/unjaggy.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/unjaggy.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/unjaggy.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/unjaggy.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/unjaggy.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/unjaggy.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/unjaggy.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/unjaggy.txt (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/vianudge.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/vianudge.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/vianudge.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/vianudge.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/vianudge.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/vianudge.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/vianudge.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/vianudge.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/vianudge.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/vianudge.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/vianudge.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/vianudge.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/vianudge.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/vianudge.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/vianudge.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/vianudge.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/vianudge.txt (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/viatrim.out.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/viatrim.out.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/viatrim.out.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/viatrim.out.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/viatrim.out.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/viatrim.out.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/viatrim.out.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/viatrim.pcb =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/viatrim.pcb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/viatrim.pcb (revision 13657) @@ -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/1.2.7/doc/user/06_feature/djopt/viatrim.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/djopt/viatrim.png =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/viatrim.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/viatrim.png (revision 13657) Property changes on: tags/1.2.7/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/1.2.7/doc/user/06_feature/djopt/viatrim.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/djopt/viatrim.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/djopt/viatrim.txt (revision 13657) @@ -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/1.2.7/doc/user/06_feature/gpmi/Credits =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/Credits (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/Credits (revision 13657) @@ -0,0 +1,11 @@ +2006...2009 +~~~~~~~~~~~ +Big thanks to DJ Delorie who added external HID support in PCB and commited +many small patches needed to get this project working in the period +when the whole project was a plugin to vanilla pcb. + +The following people helped the project with their valuable feedbacks +in the early stage: + John Griessen + Carlos Nieves Onega + Index: tags/1.2.7/doc/user/06_feature/gpmi/History =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/History (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/History (revision 13657) @@ -0,0 +1,32 @@ +History +~~~~~~~ +As of October 2006, PCB has native support for external (or dynamic +loadable) HIDs. This project is a plugin that provides scripting features. + +For a long time I have believed that good applications should be scriptable, +and really good ones should not restrict scripting to one or two languages. +For this reason I have been working on GPMI with various other developers +for years. GPMI provides a general way to split up big applications in +smaller, usually dynamic loadable parts, and encourages that some of these +parts should be written in a script language. For me, the ideal model +of an application is a small core that knows how to manipulate the +internal representation of the task and a lot of dynamic functionality +plugins and support plugins that do all the high-level job for the user. + +PCB is an old and big software, with a stable user base. Restructuring the +whole source to "GPMIize" it is not an option. Instead, a nice compromise is +implementing this functionality in a plugin that pcb can load for the users +who are interested in such extras. + +From 2006 to spring 2009 the project was on hold, because I was nagging +PCB developers to add support for customizable dialog boxes. In late March +2009, PCB developers pointed out that the interface I was waiting for had been +there for who-knows-how-long. With the help of DJ Delorie I extended the +action handling of PCB to remember action contexts, which was another showstopper. +After all obstacles were removed, I allocated a 24 hour coding session where I +finished the exporter functionality, added action binding, dialog box handling, +and layout manipulation functions. + +During the summer of 2015 I merged pcb-gpmi into pcb-rnd and made it +the default scripting engine for pcb-rnd. + Index: tags/1.2.7/doc/user/06_feature/gpmi/Makefile =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/Makefile (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/Makefile (revision 13657) @@ -0,0 +1,20 @@ +DPI_BIG=-Gsize=8,8 -Gdpi=166 +DPI=-Gsize=8,8 -Gdpi=100 + +all: gpmi_flow.png gpmi_flow_load.png gpmi_flow_reg.png gpmi_flow_menu.png gpmi_flow_exp.png + cd rosetta && make + +gpmi_flow.png: gpmi_flow.dot Makefile + dot $(DPI_BIG) -Tpng gpmi_flow.dot >$@ + +gpmi_flow_load.png: gpmi_flow_load.dot Makefile + dot $(DPI) -Tpng gpmi_flow_load.dot >$@ + +gpmi_flow_reg.png: gpmi_flow_reg.dot Makefile + dot $(DPI) -Tpng gpmi_flow_reg.dot >$@ + +gpmi_flow_menu.png: gpmi_flow_menu.dot Makefile + dot $(DPI) -Tpng gpmi_flow_menu.dot >$@ + +gpmi_flow_exp.png: gpmi_flow_exp.dot Makefile + dot $(DPI) -Tpng gpmi_flow_exp.dot >$@ Index: tags/1.2.7/doc/user/06_feature/gpmi/Porting =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/Porting (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/Porting (revision 13657) @@ -0,0 +1,5 @@ +Currently the project works on Linux only. GPMI is portable, so we need +only Makefile tweakings on pcb-gpmi to be able to compile it anywhere +where GPMI compiles. However, first I want to see some test results +from Linux users. + Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.dot =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.dot (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.dot (revision 13657) @@ -0,0 +1,63 @@ +digraph g { + rankdir=LR + splines="polyline" +# nodesep=1 +# ranksep=1.5 + + subgraph cluster_0 { + label="pcb-rnd" +# core [label="pcb-rnd core|{{HID system|plugin system}}" shape=record] + core [label="core" shape=box] + hids [label="HID system" shape=box height=2] + plugins [label="plugin system" shape=box height=2] + } + + subgraph cluster_1 { + label="GPMI" + gpmi_hid [label="gpmi HID"] + gpmi_pkg [label="gpmi package\n(host glue layer)"] + gpmi_mod1 [label="gpmi lua module\n(script glue layer)"] + gpmi_scr1 [label="lua script"] + gpmi_mod2 [label="gpmi mawk module\n(script glue layer)"] + gpmi_scr2 [label="awk script"] + } + + + + gui [label="the active\nGUI HID\n(e.g. gtk)"] + exp1 [label="PS exporer"] + exp2 [label="PNG exporer"] + + + exp1 -> hids [label="register"] + exp2 -> hids [label="register"] + + hids -> exp1 [label="drawing"] + hids -> exp2 [label="drawing"] + hids -> gui [label="drawing"] + + plugins -> gpmi_hid [label="load plugin"] + gpmi_hid -> hids [label="register"] + hids -> gpmi_hid [label="drawing"] + core -> gpmi_hid [label="event"] + + gpmi_pkg -> core [label="calls & variables"] + gpmi_pkg -> hids [label="calls & variables"] + gpmi_pkg -> gpmi_hid [label="calls & variables"] + gpmi_pkg -> plugins [label="calls & variables"] + + + gpmi_hid -> gpmi_mod1 [label="load script"] + gpmi_hid -> gpmi_mod1 [label="event"] + gpmi_hid -> gpmi_mod2 [label="load script"] + gpmi_hid -> gpmi_mod2 [label="event"] + + gpmi_mod1 -> gpmi_scr1 [label="load and exec"] + gpmi_mod1 -> gpmi_scr1 [label="event" style=dashed] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed] + + gpmi_mod2 -> gpmi_scr2 [label="load and exec"] + gpmi_mod2 -> gpmi_scr2 [label="event" style=dashed] + gpmi_scr2 -> gpmi_pkg [label="function calls" style=dashed] + +} \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.png =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.png (revision 13657) Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.dot =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.dot (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.dot (revision 13657) @@ -0,0 +1,65 @@ +digraph g { + rankdir=LR + splines="polyline" +# nodesep=1 +# ranksep=1.5 + + subgraph cluster_0 { + label="pcb-rnd" +# core [label="pcb-rnd core|{{HID system|plugin system}}" shape=record] + core [label="core" shape=box] + hids [label="HID system" shape=box height=2] + plugins [label="plugin system" shape=box height=2] + } + + subgraph cluster_1 { + label="GPMI" + gpmi_hid [label="gpmi HID"] + gpmi_pkg [label="gpmi package\n(host glue layer)"] + gpmi_mod1 [label="gpmi lua module\n(script glue layer)"] + gpmi_scr1 [label="lua script"] + gpmi_mod2 [label="gpmi mawk module\n(script glue layer)"] + gpmi_scr2 [label="awk script"] + outfile [label="export\noutput file" color=green] + } + + + + gui [label="the active\nGUI HID\n(e.g. gtk)"] + exp1 [label="PS exporer"] + exp2 [label="PNG exporer"] + + + exp1 -> hids [label="register"] + exp2 -> hids [label="register"] + + hids -> exp1 [label="drawing"] + hids -> exp2 [label="drawing"] + hids -> gui [label="drawing"] + + plugins -> gpmi_hid [label="load plugin"] + gpmi_hid -> hids [label="register"] + hids -> gpmi_hid [label="drawing" color=green] + core -> gpmi_hid [label="event"] + + gpmi_pkg -> core [label="calls & variables"] + gpmi_pkg -> hids [label="calls & variables" color=red] + gpmi_pkg -> gpmi_hid [label="calls & variables"] + gpmi_pkg -> plugins [label="calls & variables"] + + + gpmi_hid -> gpmi_mod1 [label="load script"] + gpmi_hid -> gpmi_mod1 [label="event" color=green] + gpmi_hid -> gpmi_mod2 [label="load script"] + gpmi_hid -> gpmi_mod2 [label="event"] + + gpmi_mod1 -> gpmi_scr1 [label="load and exec"] + gpmi_mod1 -> gpmi_scr1 [label="event" style=dashed color=green] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed color=red] + gpmi_scr1 -> outfile [label="write" color=green] + + gpmi_mod2 -> gpmi_scr2 [label="load and exec"] + gpmi_mod2 -> gpmi_scr2 [label="event" style=dashed] + gpmi_scr2 -> gpmi_pkg [label="function calls" style=dashed] + +} \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.png =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.png (revision 13657) Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_exp.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.dot =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.dot (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.dot (revision 13657) @@ -0,0 +1,63 @@ +digraph g { + rankdir=LR + splines="polyline" +# nodesep=1 +# ranksep=1.5 + + subgraph cluster_0 { + label="pcb-rnd" +# core [label="pcb-rnd core|{{HID system|plugin system}}" shape=record] + core [label="core" shape=box] + hids [label="HID system" shape=box height=2] + plugins [label="plugin system" shape=box height=2] + } + + subgraph cluster_1 { + label="GPMI" + gpmi_hid [label="gpmi HID"] + gpmi_pkg [label="gpmi package\n(host glue layer)"] + gpmi_mod1 [label="gpmi lua module\n(script glue layer)"] + gpmi_scr1 [label="lua script"] + gpmi_mod2 [label="gpmi mawk module\n(script glue layer)"] + gpmi_scr2 [label="awk script"] + } + + + + gui [label="the active\nGUI HID\n(e.g. gtk)"] + exp1 [label="PS exporer"] + exp2 [label="PNG exporer"] + + + exp1 -> hids [label="register"] + exp2 -> hids [label="register"] + + hids -> exp1 [label="drawing"] + hids -> exp2 [label="drawing"] + hids -> gui [label="drawing"] + + plugins -> gpmi_hid [label="load plugin" color=red] + gpmi_hid -> hids [label="register"] + hids -> gpmi_hid [label="drawing"] + core -> gpmi_hid [label="event"] + + gpmi_pkg -> core [label="calls & variables"] + gpmi_pkg -> hids [label="calls & variables"] + gpmi_pkg -> gpmi_hid [label="calls & variables" color=green] + gpmi_pkg -> plugins [label="calls & variables"] + + + gpmi_hid -> gpmi_mod1 [label="load script" color=red] + gpmi_hid -> gpmi_mod1 [label="event"] + gpmi_hid -> gpmi_mod2 [label="load script"] + gpmi_hid -> gpmi_mod2 [label="event"] + + gpmi_mod1 -> gpmi_scr1 [label="load and exec" color=red] + gpmi_mod1 -> gpmi_scr1 [label="event" style=dashed] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed color=green] + + gpmi_mod2 -> gpmi_scr2 [label="load and exec"] + gpmi_mod2 -> gpmi_scr2 [label="event" style=dashed] + gpmi_scr2 -> gpmi_pkg [label="function calls" style=dashed] + +} \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.png =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.png (revision 13657) Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_load.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.dot =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.dot (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.dot (revision 13657) @@ -0,0 +1,63 @@ +digraph g { + rankdir=LR + splines="polyline" +# nodesep=1 +# ranksep=1.5 + + subgraph cluster_0 { + label="pcb-rnd" +# core [label="pcb-rnd core|{{HID system|plugin system}}" shape=record] + core [label="core" shape=box] + hids [label="HID system" shape=box height=2] + plugins [label="plugin system" shape=box height=2] + } + + subgraph cluster_1 { + label="GPMI" + gpmi_hid [label="gpmi HID"] + gpmi_pkg [label="gpmi package\n(host glue layer)"] + gpmi_mod1 [label="gpmi lua module\n(script glue layer)"] + gpmi_scr1 [label="lua script"] + gpmi_mod2 [label="gpmi mawk module\n(script glue layer)"] + gpmi_scr2 [label="awk script"] + } + + + + gui [label="the active\nGUI HID\n(e.g. gtk)"] + exp1 [label="PS exporer"] + exp2 [label="PNG exporer"] + + + exp1 -> hids [label="register"] + exp2 -> hids [label="register"] + + hids -> exp1 [label="drawing"] + hids -> exp2 [label="drawing"] + hids -> gui [label="drawing" color=green] + + plugins -> gpmi_hid [label="load plugin"] + gpmi_hid -> hids [label="register"] + hids -> gpmi_hid [label="drawing"] + core -> gpmi_hid [label="event" color=red] + + gpmi_pkg -> core [label="calls & variables"] + gpmi_pkg -> hids [label="calls & variables" color=green] + gpmi_pkg -> gpmi_hid [label="calls & variables"] + gpmi_pkg -> plugins [label="calls & variables"] + + + gpmi_hid -> gpmi_mod1 [label="load script"] + gpmi_hid -> gpmi_mod1 [label="event" color=red] + gpmi_hid -> gpmi_mod2 [label="load script"] + gpmi_hid -> gpmi_mod2 [label="event"] + + gpmi_mod1 -> gpmi_scr1 [label="load and exec"] + gpmi_mod1 -> gpmi_scr1 [label="event" style=dashed color=red] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed color=green] + + gpmi_mod2 -> gpmi_scr2 [label="load and exec"] + gpmi_mod2 -> gpmi_scr2 [label="event" style=dashed] + gpmi_scr2 -> gpmi_pkg [label="function calls" style=dashed] + +} \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.png =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.png (revision 13657) Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_menu.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.dot =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.dot (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.dot (revision 13657) @@ -0,0 +1,64 @@ +digraph g { + rankdir=LR + splines="polyline" +# nodesep=1 +# ranksep=1.5 + + subgraph cluster_0 { + label="pcb-rnd" +# core [label="pcb-rnd core|{{HID system|plugin system}}" shape=record] + core [label="core" shape=box] + hids [label="HID system" shape=box height=2] + plugins [label="plugin system" shape=box height=2] + } + + subgraph cluster_1 { + label="GPMI" + gpmi_hid [label="gpmi HID"] + gpmi_pkg [label="gpmi package\n(host glue layer)"] + gpmi_mod1 [label="gpmi lua module\n(script glue layer)"] + gpmi_scr1 [label="lua script"] + gpmi_mod2 [label="gpmi mawk module\n(script glue layer)"] + gpmi_scr2 [label="awk script"] + } + + + + gui [label="the active\nGUI HID\n(e.g. gtk)"] + exp1 [label="PS exporer"] + exp2 [label="PNG exporer"] + + + exp1 -> hids [label="register"] + exp2 -> hids [label="register"] + + hids -> exp1 [label="drawing"] + hids -> exp2 [label="drawing"] + hids -> gui [label="drawing"] + + plugins -> gpmi_hid [label="load plugin"] + gpmi_hid -> hids [label="register"] + hids -> gpmi_hid [label="drawing"] + core -> gpmi_hid [label="event"] + + gpmi_pkg -> core [label="calls & variables" color=green] + gpmi_pkg -> hids [label="calls & variables"] + gpmi_pkg -> gpmi_hid [label="calls & variables" color=red] + gpmi_pkg -> plugins [label="calls & variables"] + + + gpmi_hid -> gpmi_mod1 [label="load script"] + gpmi_hid -> gpmi_mod1 [label="event"] + gpmi_hid -> gpmi_mod2 [label="load script"] + gpmi_hid -> gpmi_mod2 [label="event"] + + gpmi_mod1 -> gpmi_scr1 [label="load and exec"] + gpmi_mod1 -> gpmi_scr1 [label="event" style=dashed] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed color=red] + gpmi_scr1 -> gpmi_pkg [label="function calls" style=dashed color=green] + + gpmi_mod2 -> gpmi_scr2 [label="load and exec"] + gpmi_mod2 -> gpmi_scr2 [label="event" style=dashed] + gpmi_scr2 -> gpmi_pkg [label="function calls" style=dashed] + +} \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.png =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.png (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.png (revision 13657) Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_flow_reg.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/gpmi_temp_inst.txt =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/gpmi_temp_inst.txt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/gpmi_temp_inst.txt (revision 13657) @@ -0,0 +1,65 @@ +GPMI system-wide installation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The installation process is somewhat manual at this early stage. Please +follow the steps below. + +First, you'll need libgpmi - it's a general purpose script glue interface. + +A/1. svn checkout svn://repo.hu/gpmi/trunk gpmi/trunk +A/2. look at doc/languages.txt there; if you have preferred languages, +please install the -dev packages of those. My favorite is mawk, but I +think most of the example pcb scripts would be in lua. Versions should +match; it may be that gpmi works with a newer minor version out of the +box, tho. +A/3. run ./configure +A/4. check if it found the language(s) you wanted; if not, or anything +else breaks, please send me your scconfig/config.log +A/5. make +A/6. make install (as root, but see below) + +There are options to step 6: + +- if you want to check what it'd do, you could run this: + + install_root=/tmp/foo make install + + it's like DESTDIR for autotools: it will do everything but will use + /tmp/foo instead of / so you see what it'd do without using root or + messing with /usr + +- you can use make linstall instead of make install; this creates symlinks +(pointing to the binaries in your user checkout) instead of copying the +files. If gpmi changes and you need to update and recompile, you won't +need to reinstall (until the number of files change). + +- there's a make uninstall, but it's more or less untested (failed once +and worked once for me) + +Second, you'll need pcb-rnd: + +B/1. svn checkout svn://repo.hu/pcb-rnd/trunk pcb-rnd/trunk +B/2. ./configure +B/3. check the output; if anything went wrong, please send me +scconfig/config.log +B/4. make +B/5. you don't need to install it for testing: cd src; ./pcb-rnd + + +There are options in step 2: by default, if gpmi is found, it's compiled +in "buildin" mode, which means script support is compiled into the pcb-rnd +executable. An alternative is to have it as a plugin (dynamic linkable +object). This can be done using the --plugin-gpmi argument for ./configure. + + +GPMI local installation +~~~~~~~~~~~~~~~~~~~~~~~ +GPMI can be installed without root, into a local user directory (typically +under home). To achieve this, follow the above steps with the following +modifications (assuming you want to install gpmi in ~/usr): + +A/3. ./configure --prefix=~/usr +B/2. ./configure --gpmi-prefix=~/usr + +NOTE: you don't need to use install_root; gpmi will install under ~/usr as +if it was /usr. Index: tags/1.2.7/doc/user/06_feature/gpmi/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/index.html (revision 13657) @@ -0,0 +1,37 @@ + + + + pcb-rnd user manual + + + +

            pcb-rnd GPMI scripting - TOC

            + +

            Installation, configuration

            + + + +

            High level docs

            + + +

            Glue layer documentation

            + + +

            Authors, credits, misc

            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/Makefile =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/Makefile (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/Makefile (revision 13657) @@ -0,0 +1,15 @@ +ROOT=../../../../.. +GPMIDIR=$(ROOT)/src_plugins/gpmi/pcb-gpmi +ALL= actions dialogs hid layout + +all: XREF $(ALL:%=%_ref.html) + +include $(GPMIDIR)/Makefile.config + +%_ref.html REF.% : $(GPMIDIR)/gpmi_plugin/gpmi_pkg/%.h + $(ROOT)/util/genref.sh "$^" "$(ROOT)" "../packages/$*_ref.html" $(PCB_CFLAGS) >$*_ref.html + +XREF: $(ALL:%=REF.%) + cat $^ > $@ + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/XREF =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/XREF (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/XREF (revision 13657) @@ -0,0 +1,85 @@ +event ACTE_action ../packages/actions_ref.html#ACTE_action +event ACTE_gui_init ../packages/actions_ref.html#ACTE_gui_init +event ACTE_unload ../packages/actions_ref.html#ACTE_unload +function action_register ../packages/actions_ref.html#action_register +function action_arg ../packages/actions_ref.html#action_arg +function action ../packages/actions_ref.html#action +function create_menu ../packages/actions_ref.html#create_menu +enum dialog_fileselect_e ../packages/dialogs_ref.html#dialog_fileselect_e +function dialog_log ../packages/dialogs_ref.html#dialog_log +function dialog_confirm ../packages/dialogs_ref.html#dialog_confirm +function dialog_report ../packages/dialogs_ref.html#dialog_report +function dialog_prompt ../packages/dialogs_ref.html#dialog_prompt +function dialog_fileselect ../packages/dialogs_ref.html#dialog_fileselect +function dialog_beep ../packages/dialogs_ref.html#dialog_beep +function dialog_progress ../packages/dialogs_ref.html#dialog_progress +function dialog_attribute ../packages/dialogs_ref.html#dialog_attribute +enum hid_attr_type_e ../packages/hid_ref.html#hid_attr_type_e +enum EndCapStyle_e ../packages/hid_ref.html#EndCapStyle_e +event HIDE_get_export_options ../packages/hid_ref.html#HIDE_get_export_options +event HIDE_do_export_start ../packages/hid_ref.html#HIDE_do_export_start +event HIDE_do_export_finish ../packages/hid_ref.html#HIDE_do_export_finish +event HIDE_set_layer ../packages/hid_ref.html#HIDE_set_layer +event HIDE_set_color ../packages/hid_ref.html#HIDE_set_color +event HIDE_set_line_cap ../packages/hid_ref.html#HIDE_set_line_cap +event HIDE_set_line_width ../packages/hid_ref.html#HIDE_set_line_width +event HIDE_set_draw_xor ../packages/hid_ref.html#HIDE_set_draw_xor +event HIDE_set_draw_faded ../packages/hid_ref.html#HIDE_set_draw_faded +event HIDE_draw_line ../packages/hid_ref.html#HIDE_draw_line +event HIDE_draw_arc ../packages/hid_ref.html#HIDE_draw_arc +event HIDE_draw_rect ../packages/hid_ref.html#HIDE_draw_rect +event HIDE_fill_circle ../packages/hid_ref.html#HIDE_fill_circle +event HIDE_fill_polygon ../packages/hid_ref.html#HIDE_fill_polygon +event HIDE_fill_rect ../packages/hid_ref.html#HIDE_fill_rect +event HIDE_use_mask ../packages/hid_ref.html#HIDE_use_mask +event HIDE_make_gc ../packages/hid_ref.html#HIDE_make_gc +event HIDE_destroy_gc ../packages/hid_ref.html#HIDE_destroy_gc +event HIDE_fill_pcb_pv ../packages/hid_ref.html#HIDE_fill_pcb_pv +event HIDE_fill_pcb_pad ../packages/hid_ref.html#HIDE_fill_pcb_pad +function hid_create ../packages/hid_ref.html#hid_create +function hid_add_attribute ../packages/hid_ref.html#hid_add_attribute +function hid_get_attribute ../packages/hid_ref.html#hid_get_attribute +function hid_register ../packages/hid_ref.html#hid_register +function hid_gpmi_data_set ../packages/hid_ref.html#hid_gpmi_data_set +function hid_gpmi_data_get ../packages/hid_ref.html#hid_gpmi_data_get +function hid_string2val ../packages/hid_ref.html#hid_string2val +enum layout_object_mask_e ../packages/layout_ref.html#layout_object_mask_e +enum layout_object_coord_e ../packages/layout_ref.html#layout_object_coord_e +enum layout_flag_e ../packages/layout_ref.html#layout_flag_e +enum layer_field_e ../packages/layout_ref.html#layer_field_e +function layout_search_box ../packages/layout_ref.html#layout_search_box +function layout_search_selected ../packages/layout_ref.html#layout_search_selected +function layout_search_found ../packages/layout_ref.html#layout_search_found +function layout_search_get ../packages/layout_ref.html#layout_search_get +function layout_search_free ../packages/layout_ref.html#layout_search_free +function layout_obj_coord ../packages/layout_ref.html#layout_obj_coord +function layout_obj_type ../packages/layout_ref.html#layout_obj_type +function layout_obj_move ../packages/layout_ref.html#layout_obj_move +function layout_arc_angles ../packages/layout_ref.html#layout_arc_angles +function layout_create_line ../packages/layout_ref.html#layout_create_line +function layout_create_via ../packages/layout_ref.html#layout_create_via +function layout_create_arc ../packages/layout_ref.html#layout_create_arc +function layout_switch_to_layer ../packages/layout_ref.html#layout_switch_to_layer +function layout_get_current_layer ../packages/layout_ref.html#layout_get_current_layer +function layout_resolve_layer ../packages/layout_ref.html#layout_resolve_layer +function layout_get_max_possible_layer ../packages/layout_ref.html#layout_get_max_possible_layer +function layout_get_max_copper_layer ../packages/layout_ref.html#layout_get_max_copper_layer +function layout_get_max_layer ../packages/layout_ref.html#layout_get_max_layer +function layout_layer_name ../packages/layout_ref.html#layout_layer_name +function layout_layer_color ../packages/layout_ref.html#layout_layer_color +function layout_layer_field ../packages/layout_ref.html#layout_layer_field +function layout_get_page_width ../packages/layout_ref.html#layout_get_page_width +function layout_get_page_height ../packages/layout_ref.html#layout_get_page_height +function layout_set_page_size ../packages/layout_ref.html#layout_set_page_size +function mil2pcb_multiplier ../packages/layout_ref.html#mil2pcb_multiplier +function mm2pcb_multiplier ../packages/layout_ref.html#mm2pcb_multiplier +function current_grid_unit ../packages/layout_ref.html#current_grid_unit +function debug_draw_request ../packages/layout_ref.html#debug_draw_request +function debug_draw_flush ../packages/layout_ref.html#debug_draw_flush +function debug_draw_finish ../packages/layout_ref.html#debug_draw_finish +function debug_draw_dctx ../packages/layout_ref.html#debug_draw_dctx +function draw_set_color ../packages/layout_ref.html#draw_set_color +function draw_set_line_width ../packages/layout_ref.html#draw_set_line_width +function draw_set_draw_xor ../packages/layout_ref.html#draw_set_draw_xor +function draw_set_draw_faded ../packages/layout_ref.html#draw_set_draw_faded +function draw_line ../packages/layout_ref.html#draw_line Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/actions.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/actions.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/actions.html (revision 13657) @@ -0,0 +1,123 @@ + + +

            The actions package

            + +The action package is used to register actions and menus in PCB and +to execute existing actions. In PCB actions +are generated when the user selects a menu, presses a key or issues a +command on the PCB command line. + +

            Registration of new actions

            +The script may register new actions +using arbitrary action names. If any of the registered actions is +detected, an ACTE_action event is sent to the script. If multiple +actions are used in a script, argument name of the event handler +can be used to identify the triggering action. (This may be time consuming +in scripting languages (a series of string comparison) - those scripts +binding to frequent actions should not bind to too many different actions.) +pcb-gpmi guarantees that the event handler of a script is triggered only +when an action is caught that previously was registered by the same script. +

            +The process of binding an action: +

              +
            1. create an event handler for event ACTE_action +
            2. register one or more actions using function action_register +
            3. optional: when the event handler is triggered, check argument name (for scripts with multiple actions registered) +
            4. optional: use argument argc and function action_arg to fetch action arguments +
            5. optional: use arguments x, y to learn the cursor position on the layout. +
            + +Example (written in lua): +
            +-- load the package
            +PkgLoad("pcb-gpmi/actions", 0);
            +
            +-- action callback
            +function ev_action(id, name, argc, x, y)
            +	if name == "cake" then
            +		size = action_arg(1);
            +		-- put cake drawing code here
            +	else
            +		-- must be candy
            +		amount = action_arg(1);
            +		-- put candy drawing code here
            +	end
            +end
            +
            +-- register and bind action
            +action_register("cake",  "cake center xy?", "cake service", "cake(size)", "");
            +action_register("candy", "candy cloud center xy?", "cake service", "candy(amount)", "");
            +Bind("ACTE_action", "ev_action");
            +
            +

            +When the script is unloaded all actions the script registered +are removed from pcb-rnd automatically. + +

            Executing actions

            +An existing action can be executed using the action() call. The only one +argument is a command line string. The syntax is the same as in pcb +command line. + +Example (written in lua): +
            +PkgLoad("pcb-rnd-gpmi/actions", 0);
            +
            +function ev_action1(id, name, argc, x, y)
            +	action("undo()")
            +	action("undo()")
            +end
            +
            +-- register and bind action
            +action_register("untwo", "", "undo twice", "untwo()", "CONTEXT!");
            +
            +

            +The above script registers a new action called untwo(). When untwo() is executed, +it executes action undo() twice. + + +

            Creating menus

            +It is possible to insert menus and submenus runtime, using the call +create_menu(). The script should do this only after the gui has been initialized. +The most common way is to create all menus from the ACTE_gui_init event, +which is called after the gui finished setting up. +

            +The first argument of create_menu() is the menu path. The path is a list +of visible menu names separated by slashes (e.g. "/main_menu/File/Save as..." means +"File" menu, "Save as..." submenu). +

            +Paths are interpreted as menu paths, which are a slightly simplified version +of lihata paths found in menu.lht. Basically there's a main directory directly +under root that determines the type of the menu: +

            +

              +
            • /main_menu/ is the menubar +
            • /popups/something/ is a popup menu called something; the lesstif HID does + not support popups; popups are popped up by actions. +
            +

            +The simplification compared to lihata paths is that only menu and submenu +names are on the path, so lihata nodes like "li:submenu" should be ignored. +In other words, the path represents how the menus can be reached from the user +interface, plus a "main menu type prefix" as discussed above. +

            +By convention, scripts should +create new menu items under the "/main_menu/Plugins/" menu. +

            +The following example lua script registers a new menu item +

            +PkgLoad("pcb-rnd-gpmi/actions", 0);
            +
            +function ev_gui_init(argc, argv)
            +	create_menu("/main_menu/Plugins/foo", "undo()", "o", "Ctrl<Key>o", "tooltip for foo");
            +end
            +
            +-- register and bind action
            +Bind("ACTE_gui_init", "ev_gui_init");
            +
            +

            +When the user clicks on the menu, the action script specified in the second argument +of create_menu() is executed. Thus the script usually registers a new action +first then registers one or more menu items executing those actions. + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/actions_ref.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/actions_ref.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/actions_ref.html (revision 13657) @@ -0,0 +1,82 @@ + + +

            PCB GPMI

            +

            Reference manual for package actions

            +Automatically generated from actions.h + +

            Events

            +
            +

            Events do not have return value. The first argument is always the even id. Event handlers defined in scripts get all event arguments converted to string (types below are informational). + +

            ACTE_action(int event_id, const char* name, int argc, int x, int y)

            +
            + Generated when an action registered by the script is executed.
            +   Arguments:
            +    name: name of the action (as registered using function action_register())
            +    argc: number of arguments. Arguments can be accessed using function action_arg
            +    x, y: optional coords, if need_xy was not empty at action_register 
            +
            +
            +

            ACTE_gui_init(int event_id, int argc, char** argv)

            +
            + Generated right after gui initialization, before the gui main loop.
            +   Arguments:
            +    argc: number of arguments the gui was initialized with.
            +    argv[]: arguments the gui was initialized with - unaccessible for the scripts. 
            +
            +
            +

            ACTE_unload(int event_id, const char* conffile)

            +
            + Generated right before unloading a script to give the script a chance
            +   to clean up.
            +   Arguments:
            +    conffile: the name of the config file that originally triggered loading the script, or empty if the script was loaded from the gui. 
            +
            +
            +

            Functions

            +
            +

            The following functions are registered in script context. + +

            int action_register(const char* name, const char* need_xy, const char* description, const char* syntax)

            +
            + Register an action in PCB - when the action is executed, event
            +   ACTE_action is generated with the action name.
            +   Multiple actions can be registered. Any action registered by the script
            +   will trigger an ACTE_event sent to the script.
            +   Arguments:
            +    name: name of the action
            +    need_xy: the question the user is asked when he needs to choose a coordinate; if empty, no coordinate is asked
            +    description: description of the action (for the help)
            +    syntax: syntax of the action (for the help)
            +   Returns 0 on success.
            + 
            +
            +
            +

            const char* action_arg(int argn)

            +
            + extract the (argn)th event argument for the current action (makes sense only in an ACTE_action event handler 
            +
            +
            +

            int action(const char* cmdline)

            +
            + call an existing action using PCB syntax (e.g. foo(1, 2, 3))
            +   Returns non-zero on error; generally returns value of the action
            +   (which is also non-zero on error). 
            +
            +
            +

            void create_menu(const char* path, const char* action, const char* mnemonic, const char* hotkey, const char* tooltip)

            +
            + Create a new menu or submenu at path. Missing parents are created
            +   automatically with empty action, mnemonic, hotkey and tooltip.
            +   Arguments:
            +    path: the full path of the new menu
            +    action: this action is executed when the user clicks on the menu
            +    mnemonic: which letter to underline in the menu text (will be the fast-jump-there key once the menu is open)
            +    hotkey: when this key is pressed in the main gui, the action is also triggered; the format is modifiers<Key>letter, where modifiers is Alt, Shift or Ctrl. This is the same syntax that is used in the .res files.
            +    tooltip: short help text 
            +
            +
            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs.html (revision 13657) @@ -0,0 +1,47 @@ + + +

            dialogs package

            + The purpose of this package is to expose the dialog box handling interface + of the active GUI hid. Using this package scripts can pop up dialog boxes + to inform or ask the user. If there is no active GUI, call logs are dumped + on stderr. Note: message arguments usually may contain newline (\n) characters + to split the message. + +

            Common conventions

            + Dialog boxes are blocking calls to the GUI HID: when the script + calls a dialog box, the script is suspended until the dialog box + is closed by the user. In other words, dialog boxes behave + as regular function calls from the scripts: when they return, + the dialog is over and the result is known. +

            + The only exception is dialog_progress(), which opens or + updates or closes the already open progress dialog box, and + returns immediately (even when the box is left open). + +

            Simple dialogs vs. custom dialogs

            + Most of the calls will pop up a static dialog box. Static means + that widgets are predefined by the GUI HID. The script + is free to fill in data, but can not change the basic structure of + the dialog box. For example dialog_confirm(), dialog_prompt(), + dialog_fileselect() are static. +

            + When the script needs a custom, dynamic dialog box, it needs to + create an attribute dialog. The script sets up a HID + structure using the hid package, builds up all the input fields + then calls dialog_attribute() with the hid. + +

            Progress dialogs

            + + The script should call dialog_progress() periodically from a process that + runs time consuming calculations and check the return value and break + the loop on cancel. The process should have an idea of how long it + will take. This is passed on in argument total. As long as + argument so_far is less than total, the dialog is + open. +

            + After the process has finished, a call with so_far=total+1 should be + made to make sure the window is closed. If the call returns non-zero, + the process should be cancelled. + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs_ref.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs_ref.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/dialogs_ref.html (revision 13657) @@ -0,0 +1,105 @@ + + +

            PCB GPMI

            +

            Reference manual for package dialogs

            +Automatically generated from dialogs.h + +

            Enums

            +
            +

            Enum values should be passed on as strings. + +

            dialog_fileselect_e

            +
            + Filter on what files a file select dialog should list 
            +
            + +
            value meaning +
            FS_NONE none of the below +
            FS_READ when the selected file will be read, not written (HID_FILESELECT_READ) +
            FS_NOT_EXIST the function calling hid->fileselect will deal with the case when the selected file already exists. If not given, then the gui will prompt with an "overwrite?" prompt. Only used when writing. (HID_FILESELECT_MAY_NOT_EXIST) +
            FS_TEMPLATE the call is supposed to return a file template (for gerber output for example) instead of an actual file. Only used when writing. (HID_FILESELECT_IS_TEMPLATE) +
            +
            +

            Functions

            +
            +

            The following functions are registered in script context. + +

            void dialog_log(const char* msg)

            +
            + Append a msg to the log (log window and/or stderr). 
            +
            +
            +

            int dialog_confirm(const char* msg, const char* ok, const char* cancel)

            +
            + Ask the user for confirmation (usually using a popup). Returns 0 for
            +   cancel and 1 for ok.
            +   Arguments:
            +     msg: message to the user
            +     ok: label of the OK button
            +     cancel: label of the cancel button
            +  Arguments "ok" and "cancel" may be empty (or NULL) in which
            +  case the GUI will use the default (perhaps localized) labels for
            +  those buttons. 
            +
            +
            +

            void dialog_report(const char* title, const char* msg)

            +
            + Pop up a report dialog.
            +   Arguments:
            +     title: title of the window
            +     msg: message 
            +
            +
            +

            char* dialog_prompt(const char* msg, const char* default_)

            +
            + Ask the user to input a string (usually in a popup).
            +   Arguments:
            +     msg: message or question text
            +     default_: default answer (this may be filled in on start)
            +   Returns the answer. 
            +
            +
            +

            char* dialog_fileselect(const char* title, const char* descr, char* default_file_, char* default_ext, const char* history_tag, dialog_fileselect_t flags)

            +
            + Pops up a file selection dialog.
            +   Arguments:
            +     title: window title
            +     descr: description
            +     default_file_
            +     default_ext: default file name extension
            +     history_tag
            +     flags: one or more flags (see below)
            +   Returns the selected file or NULL (empty). 
            +
            +
            +

            void dialog_beep(void)

            +
            + Audible beep 
            +
            +
            +

            int dialog_progress(int so_far, int total, const char* message)

            +
            + Request the GUI hid to draw a progress bar.
            +   Arguments:
            +     int so_far: achieved state
            +     int total: maximum state
            +     const char *message: informs the users what they are waiting for
            +   If so_far is bigger than total, the progress bar is closed.
            +   Returns nonzero if the user wishes to cancel the operation.
            +
            +
            +
            +

            int dialog_attribute(hid_t* hid, const char* title, const char* descr)

            +
            + Pop up an attribute dialog; content (widgets) of the dialog box are coming
            +   from hid (see the hid package).
            +   Arguments:
            +     hid: widgets
            +     title: title of the window
            +     descr: description printed in the dialog 
            +
            +
            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/event_id.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/event_id.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/event_id.html (revision 13657) @@ -0,0 +1,20 @@ + + +

            event_id

            + +The first argument passed to an event handler is always the event ID. +It is useful if there are several GPMI events with the same arguments and +the script wants to bind them all to the same event handler. In that case +using event_id the event handler can determine which event triggered the +call. This design is similar to the signal handler documented in +signal(2). + +

            + +The case described above (dispatcher in the event handler) is rare. +Most users will bind one event to one function and can safely ignore this +argument. Nevertheless it must present as the first argument +on the event handler's argument list. + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/hid.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/hid.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/hid.html (revision 13657) @@ -0,0 +1,76 @@ + + +

            hid package

            + +The hid package has two purposes: +
              +
            • it is glue layer for exporter dialog boxes and attribute dialog boxes; +
            • it can register exporter HIDs in PCB +
            + +

            Building a custom dialog box

            +First hid_create() needs to be called. It returns a new hid_t, which is +an opaque structure for the package that is used to describe attributes of +an attribute dialog or an exporter hid. Attributes are added using +hid_add_attribute(), which returns an unique ID of the attribute. The +attribute ID can be used later for querying attribute value set by the +user using hid_get_attribute(). +

            +The process of building a dialog box is closed by a call to +

              +
            • hid_register(), which registers a new exporter hid using the + attributes of the dialog box; or +
            • dialog_attribute() (of the dialog package) which pops up a custom + dialog box immediately. +
            + +

            Registering an exporter

            + Function hid_register() registers the hid as an exporter. Should be + called after all attributes have been added using hid_add_attribute(). + The export is coordinated by pcb core; when the user request an export + using the exporter, a series of events are delivered to the script: +
              +
            1. envelope events to set up exporting +
            2. many draw events to actually export the objects +
            3. an envelope event to finish exporting +
            + +

            Envelope: events generated before or after exporting

            +
              +
            • HIDE_get_export_options(void *hid): Generated before get_exporter_options returns the option list to the GUI hid +
            • HIDE_do_export_start(void *hid): Generated before export redraw starts +
            • HIDE_do_export_finish(void *hid): Generated after export redraw finished +
            + +

            Drawing: events generated during exporting

            + Note: there may be multiple gcs (graphic contexts), each having its own color, line + properties, xor drawing and faded state. Graphic contexts are created + and destroyed by the following events: +
              +
            • HIDE_make_gc(void *hid, void *gc); +
            • HIDE_destroy_gc(void *hid, void *gc); +
            + + Gc properties are changed by the following events: +
              +
            • HIDE_set_layer(void *hid, const char *name, int group); +
            • HIDE_set_color(void *hid, void *gc, const char *name); +
            • HIDE_set_line_cap(void *hid, void *gc, EndCapStyle style); +
            • HIDE_set_line_width(void *hid, void *gc, int width); +
            • HIDE_set_draw_xor(void *hid, void *gc, int xor); +
            • HIDE_set_draw_faded(void *hid, void *gc, int faded); +
            + + Finally, the actual drawing operations: +
              +
            • HIDE_draw_line(void *hid, void *gc, int x1, int y1, int x2, int y2); +
            • HIDE_draw_arc(void *hid, void *gc, int cx, int cy, int xradius, int yradius, int start_angle, int delta_angle); +
            • HIDE_draw_rect(void *hid, void *gc, int x1, int y1, int x2, int y2); +
            • HIDE_fill_circle(void *hid, void *gc, int cx, int cy, int radius); +
            • HIDE_fill_polygon(void *hid, void *gc, int n_coords, int *x, int *y); +
            • HIDE_fill_rect(void *hid, void *gc, int x1, int y1, int x2, int y2); +
            • HIDE_use_mask(void *hid, int use_it); [TODO] +
            + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/hid_ref.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/hid_ref.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/hid_ref.html (revision 13657) @@ -0,0 +1,205 @@ + + +

            PCB GPMI

            +

            Reference manual for package hid

            +Automatically generated from hid.h + +

            Enums

            +
            +

            Enum values should be passed on as strings. + +

            hid_attr_type_e

            +
            + Type of an HID attribute (usually a widget on an attribute dialog box) 
            +
            + +
            value meaning +
            HIDA_Label non-editable label displayed on the GUI +
            HIDA_Integer a signed integer value +
            HIDA_Real a floating point value +
            HIDA_String one line textual input +
            HIDA_Boolean true/false boolean value +
            HIDA_Enum select an item of a predefined list +
            HIDA_Mixed TODO +
            HIDA_Path path to a file or directory +
            HIDA_Unit select a dimension unit +
            HIDA_Coord enter a coordinate +
            +
            +

            EndCapStyle_e

            +
            + Line or arc ending style 
            +
            + +
            value meaning +
            Trace_Cap filled circle (trace drawing) +
            Square_Cap rectangular lines (square pad) +
            Round_Cap round pins or round-ended pads, thermals +
            Beveled_Cap octagon pins or bevel-cornered pads +
            +
            +

            Events

            +
            +

            Events do not have return value. The first argument is always the even id. Event handlers defined in scripts get all event arguments converted to string (types below are informational). + +

            HIDE_get_export_options(int event_id, void* hid)

            +
            + Called before get_exporter_options returns the option list to the GUI hid 
            +
            +
            +

            HIDE_do_export_start(int event_id, void* hid)

            +
            + Called before export redraw starts 
            +
            +
            +

            HIDE_do_export_finish(int event_id, void* hid)

            +
            + Called after export redraw finished 
            +
            +
            +

            HIDE_set_layer(int event_id, void* hid, const char* name, int group, int empty)

            +
            + PCB callback events for drawing: change layer 
            +
            +
            +

            HIDE_set_color(int event_id, void* hid, void* gc, const char* name)

            +
            + PCB callback events for drawing: change drawing color 
            +
            +
            +

            HIDE_set_line_cap(int event_id, void* hid, void* gc, EndCapStyle style)

            +
            + PCB callback events for drawing: change drawing line cap style
            +
            +
            +

            HIDE_set_line_width(int event_id, void* hid, void* gc, int width)

            +
            + PCB callback events for drawing: change drawing line width 
            +
            +
            +

            HIDE_set_draw_xor(int event_id, void* hid, void* gc, int xor)

            +
            + PCB callback events for drawing: toggle xor drawing method 
            +
            +
            +

            HIDE_set_draw_faded(int event_id, void* hid, void* gc, int faded)

            +
            + PCB callback events for drawing: toggle faded drawing method 
            +
            +
            +

            HIDE_draw_line(int event_id, void* hid, void* gc, int x1, int y1, int x2, int y2)

            +
            + PCB callback events for drawing: draw a line 
            +
            +
            +

            HIDE_draw_arc(int event_id, void* hid, void* gc, int cx, int cy, int xradius, int yradius, double start_angle, double delta_angle)

            +
            + PCB callback events for drawing: draw an arc from center cx;cy 
            +
            +
            +

            HIDE_draw_rect(int event_id, void* hid, void* gc, int x1, int y1, int x2, int y2)

            +
            + PCB callback events for drawing: draw a rectangle 
            +
            +
            +

            HIDE_fill_circle(int event_id, void* hid, void* gc, int cx, int cy, int radius)

            +
            + PCB callback events for drawing: draw a filled circle 
            +
            +
            +

            HIDE_fill_polygon(int event_id, void* hid, void* gc, int n_coords, int* x, int* y)

            +
            + PCB callback events for drawing: draw a filled polygon 
            +
            +
            +

            HIDE_fill_rect(int event_id, void* hid, void* gc, int x1, int y1, int x2, int y2)

            +
            + PCB callback events for drawing: draw a filled rectangle 
            +
            +
            +

            HIDE_use_mask(int event_id, void* hid, int use_it)

            +
            + PCB callback events for drawing: TODO 
            +
            +
            +

            HIDE_make_gc(int event_id, void* hid, void* gc)

            +
            + PCB callback events for drawing: create a new graphical context 
            +
            +
            +

            HIDE_destroy_gc(int event_id, void* hid, void* gc)

            +
            + PCB callback events for drawing: destroy a graphical context 
            +
            +
            +

            HIDE_fill_pcb_pv(int event_id, void* hid, void* fg_gc, void* bg_gc, void* pad, int drawHole, int mask)

            +
            + PCB callback events for drawing: TODO 
            +
            +
            +

            HIDE_fill_pcb_pad(int event_id, void* hid, void* pad, int clear, int mask)

            +
            + PCB callback events for drawing: TODO 
            +
            +
            +

            Functions

            +
            +

            The following functions are registered in script context. + +

            hid_t* hid_create(char* hid_name, char* description)

            +
            + Creates a new hid context. Name and description matters only if the hid is
            +registered as an exporter later. 
            +
            +
            +

            int hid_add_attribute(hid_t* hid, char* attr_name, char* help, hid_attr_type_t type, int min, int max, char* default_val)

            +
            + Append an attribute in a hid previously created using hid_create().
            +   Arguments:
            +     hid: hid_t previously created using hid_create()
            +     attr_name: name of the attribute
            +     help: help text for the attribute
            +     type: type of the attribute (input widget type)
            +     min: minimum value of the attribute, if type is integer or real)
            +     max: maximum value of the attribute, if type is integer or real)
            +     default_val: default value of the attribute
            +  Returns an unique ID of the attribute the caller should store for
            +  later reference. For example this ID is used when retrieving the
            +  value of the attribute after the user finished entering data in
            +  the dialog. 
            +
            +
            +

            char* hid_get_attribute(hid_t* hid, int attr_id)

            +
            + Query an attribute from the hid after dialog_attributes() returned.
            +   Arguments:
            +     hid: hid_t previously created using hid_create()
            +     attr_id: the unique ID of the attribute (returned by hid_add_attribute())
            +   Returns the value (converted to string) set by the user. 
            +
            +
            +

            int hid_register(hid_t* hid)

            +
            + Register the hid; call it after a hid is created and its attributes
            +   are all set up 
            +
            +
            +

            void hid_gpmi_data_set(hid_t* h, void* data)

            +
            + For internal use 
            +
            +
            +

            hid_t* hid_gpmi_data_get(HID* h)

            +
            + For internal use 
            +
            +
            +

            HID_Attr_Val hid_string2val(const hid_attr_type_t type, const char* str)

            +
            + For internal use 
            +
            +
            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/layout.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/layout.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/layout.html (revision 13657) @@ -0,0 +1,58 @@ + + +

            layout package

            + +Layout package searches and manipulates the current layout. Dimension units +are in nanometer unless otherwise mentioned. + +

            Page: board dimensions

            + Functions used to query or set width and height of the drawing: +
              +
            • int layout_get_page_width(); +
            • int layout_get_page_height(); +
            • void layout_set_page_size(int width, int height); +
            + +

            Layer manipulation

            +Most functions perform operations similar to user commands affecting +the current layer. +The following few calls can change the current layer. Warning: this is the +same current layer as the user's; the script most probably wants to save +the current layer before changing it and then restore it after the operation. +
              +
            • int layout_resolve_layer(const char *name): resolve layer number by name (case sensitive); returns negative number if not found +
            • int layout_get_current_layer(): returns the number of the current layer +
            • void layout_switch_to_layer(int layer): switch to layer (further actions will take place there) +
            +

            + +

            Object searches

            + Search results are collected on lists identified by their name (search_ID). + If a new search is done with the same name, old search results for that + name are discarded. + Search functions return the number of objects found (size of the list) that can + be then used while querying the results using layout_search_get(). + Results should be freed using layout_search_free() when they are no + longer needed. +

            + TODO: validity of a list in time +

            +Once the search list is ready, the script can iterate over it and resolve +the object handle of each object found, using layout_search_get(). Having +an object handle, The layout_obj_*() functions may be used by the script +to access fields of an object structure. + +

            Create new objects

            + The layout_create_*() calls are used to create new objects on the current + layer (set by layout_switch_to_layer()). + + +

            API reference - page, units and coordinates

            +(angles are in radian) +TODO + +

            API reference - debug draw

            +TODO + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/packages/layout_ref.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/packages/layout_ref.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/packages/layout_ref.html (revision 13657) @@ -0,0 +1,300 @@ + + +

            PCB GPMI

            +

            Reference manual for package layout

            +Automatically generated from layout.h + +

            Enums

            +
            +

            Enum values should be passed on as strings. + +

            layout_object_mask_e

            +
            + Object type search mask bits 
            +
            + +
            value meaning +
            OM_LINE lines (traces, silk lines, not font) +
            OM_TEXT text written using the font +
            OM_POLYGON polygons, including rectangles +
            OM_ARC arcs, circles +
            OM_VIA vias and holes which are not part of a footprint +
            OM_PIN pins/pads of a footprint +
            OM_ANY shorthand for "find anything" +
            +
            +

            layout_object_coord_e

            +
            + Which coordinate of the object is referenced 
            +
            + +
            value meaning +
            OC_BX1 bounding box X1 +
            OC_BX2 bounding box X2 +
            OC_BY1 bounding box Y1 +
            OC_BY2 bounding box Y2 +
            OC_P1X point 1 X +
            OC_P2X point 2 X +
            OC_P1Y point 1 Y +
            OC_P2Y point 2 Y +
            OC_OBJ the whole object +
            OC_P1 point 1 is P1X +
            OC_P2 point 2 is P2X +
            +
            +

            layout_flag_e

            +
            + of layout_object_coord_t 
            +
            + +
            value meaning +
            FL_NONE <comment missing in the header> +
            FL_SHOWNUMBER <comment missing in the header> +
            FL_LOCALREF <comment missing in the header> +
            FL_CHECKPLANS <comment missing in the header> +
            FL_SHOWDRC <comment missing in the header> +
            FL_RUBBERBAND <comment missing in the header> +
            FL_DESCRIPTION <comment missing in the header> +
            FL_NAMEONPCB <comment missing in the header> +
            FL_AUTODRC <comment missing in the header> +
            FL_ALLDIRECTION <comment missing in the header> +
            FL_SWAPSTARTDIR <comment missing in the header> +
            FL_UNIQUENAME <comment missing in the header> +
            FL_CLEARNEW <comment missing in the header> +
            FL_SNAPPIN <comment missing in the header> +
            FL_SHOWMASK <comment missing in the header> +
            FL_THINDRAW <comment missing in the header> +
            FL_ORTHOMOVE <comment missing in the header> +
            FL_LIVEROUTE <comment missing in the header> +
            FL_THINDRAWPOLY <comment missing in the header> +
            FL_LOCKNAMES <comment missing in the header> +
            FL_ONLYNAMES <comment missing in the header> +
            FL_NEWFULLPOLY <comment missing in the header> +
            FL_HIDENAMES <comment missing in the header> +
            FL_THERMALSTYLE1 <comment missing in the header> +
            FL_THERMALSTYLE2 <comment missing in the header> +
            FL_THERMALSTYLE3 <comment missing in the header> +
            FL_THERMALSTYLE4 <comment missing in the header> +
            FL_THERMALSTYLE5 <comment missing in the header> +
            +
            +

            layer_field_e

            +
            + Field name of the layer structure 
            +
            + +
            value meaning +
            LFLD_NUM_LINES number of lines on the layer +
            LFLD_NUM_TEXTS number of texts on the layer +
            LFLD_NUM_POLYS number of polygons on the layer +
            LFLD_NUM_ARCS number of arcs on the layer +
            LFLD_VISIBLE non-zero if the layer is visible +
            LFLD_NODRC non-zero if the layer doesn't use DRC +
            +
            +

            Functions

            +
            +

            The following functions are registered in script context. + +

            int layout_search_box(const char* search_ID, layout_object_mask_t obj_types, int x1, int y1, int x2, int y2)

            +
            + creates a new search and adds all objects that matches obj_types mask within the given rectangle on the current layer
            +   Arguments:
            +     search_ID: unique name of the search (overwrites existing search on the same name)
            +     obj_types: on or more object types
            +     x1, y1, x2, y2: box the search is done within (PCB coords)
            +   Returns the number of object on the search list. 
            +
            +
            +

            int layout_search_selected(const char* search_ID, layout_object_mask_t obj_types)

            +
            + creates a new search and adds all selected objects
            +   Arguments:
            +     search_ID: unique name of the search (overwrites existing search on the same name)
            +     obj_types: on or more object types
            +   Returns the number of object on the search list. 
            +
            +
            +

            int layout_search_found(const char* search_ID, layout_object_mask_t obj_types)

            +
            + creates a new search and adds all found objects (the green highlight)
            +   Arguments:
            +     search_ID: unique name of the search (overwrites existing search on the same name)
            +     obj_types: on or more object types
            +   Returns the number of object on the search list. 
            +
            +
            +

            layout_object_t* layout_search_get(const char* search_ID, int n)

            +
            + Returns the nth object from a search list (or NULL pointer if n is beyond the list) 
            +
            +
            +

            int layout_search_free(const char* search_ID)

            +
            + Frees all memory related to a search. Returns 0 on success.
            +   Argument:
            +     search_ID: unique name of the search (requires an existing search) 
            +
            +
            +

            int layout_obj_coord(layout_object_t* obj, layout_object_coord_t coord)

            +
            + Return the requested coord of an object; except for the bounding box
            +    coordinates, the meaning of coordinates are object-specific.
            +    Point 1 and point 2 are usually endpoints of the object (line, arc),
            +    "the whole object" coordinate is a central point. 
            +
            +
            +

            layout_object_mask_t layout_obj_type(layout_object_t* obj)

            +
            + Return the type of an object (always a single bit) 
            +
            +
            +

            int layout_obj_move(layout_object_t* obj, layout_object_coord_t coord, int dx, int dy)

            +
            + Change location of an object or parts of the object (like move endpoint of a line);
            +   Arguments:
            +     obj: the object
            +     coord: which coordinate to drag (e.g. move only the endpoint)
            +     dx, dy: relative x and y coordinates the selected coordinate is displaced by
            +   Returns 0 on success 
            +
            +
            +

            int layout_arc_angles(layout_object_t* obj, int relative, int start, int delta)

            +
            + change angles of an arc; start and delta are relative if relative is non-zero; returns 0 on success 
            +
            +
            +

            int layout_create_line(int x1, int y1, int x2, int y2, int thickness, int clearance, layout_flag_t flags)

            +
            + create a line 
            +
            +
            +

            int layout_create_via(int x, int y, int thickness, int clearance, int mask, int hole, const char* name, layout_flag_t flags)

            +
            + create a named via 
            +
            +
            +

            int layout_create_arc(int x, int y, int width, int height, int sa, int dir, int thickness, int clearance, layout_flag_t flags)

            +
            + create a new arc; sa is start angle, dir is delta angle 
            +
            +
            +

            void layout_switch_to_layer(int layer)

            +
            + switch to layer (further layer-specific actions will take place there) 
            +
            +
            +

            int layout_get_current_layer()

            +
            + returns the number of the current layer 
            +
            +
            +

            int layout_resolve_layer(const char* name)

            +
            + resolve layer number by name (case sensitive); returns negative number if not found 
            +
            +
            +

            int layout_get_max_possible_layer()

            +
            + return the theoretical number of layers supported by PCB 
            +
            +
            +

            int layout_get_max_layer()

            +
            + return the actual number of layers on the current design 
            +
            +
            +

            const char* layout_layer_name(int layer)

            +
            + return the name of a layer 
            +
            +
            +

            const char* layout_layer_color(int layer)

            +
            + return the color of a layer 
            +
            +
            +

            int layout_layer_field(int layer, layer_field_t fld)

            +
            + return an integer field of a layer 
            +
            +
            +

            int layout_get_page_width()

            +
            + query or set width and height of the drawing 
            +
            +
            +

            int layout_get_page_height()

            +
            +<comment missing in the header>
            +
            +
            +

            void layout_set_page_size(int width, int height)

            +
            +<comment missing in the header>
            +
            +
            +

            double mil2pcb_multiplier()

            +
            + -- coordinate system -- (coord.c) 
            +
            +
            +

            double mm2pcb_multiplier()

            +
            +<comment missing in the header>
            +
            +
            +

            const char* current_grid_unit()

            +
            +<comment missing in the header>
            +
            +
            +

            int debug_draw_request(void)

            +
            + Initialize debug drawing; returns 1 if worked, 0 if denied 
            +
            +
            +

            void debug_draw_flush(void)

            +
            + Flush the drawing 
            +
            +
            +

            void debug_draw_finish(dctx_t* ctx)

            +
            + Finish (close) drawing 
            +
            +
            +

            dctx_t* debug_draw_dctx(void)

            +
            + Get the draw context of debug draw 
            +
            +
            +

            void draw_set_color(dctx_t* ctx, const char* name)

            +
            + Debug draw style: set drawing color 
            +
            +
            +

            void draw_set_line_width(dctx_t* ctx, int width)

            +
            + Debug draw style: set line width 
            +
            +
            +

            void draw_set_draw_xor(dctx_t* ctx, int xor)

            +
            + Debug draw style: set whether drawing should happen in xor 
            +
            +
            +

            void draw_set_draw_faded(dctx_t* ctx, int faded)

            +
            + Debug draw style: set whether drawing should happen in faded mode  
            +
            +
            +

            void draw_line(dctx_t* ctx, int x1_, int y1_, int x2_, int y2_)

            +
            + Debug draw: draw a line using the current style settings 
            +
            +
            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc (revision 13657) @@ -0,0 +1,2 @@ +Create a new action hello() that prints "Hello world!" in the message log. + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name (revision 13657) @@ -0,0 +1 @@ +hello world (text, log) Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk (revision 13657) @@ -0,0 +1,14 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/actions", 0); + PkgLoad("pcb-rnd-gpmi/dialogs", 0); +} + +function ev_action(id, name, argc, x, y) +{ + dialog_log("Hello world!\n"); +} + +BEGIN { + Bind("ACTE_action", "ev_action"); + action_register("hello", "", "log hello world", "hello()"); +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash (revision 13657) @@ -0,0 +1,18 @@ +#!/bin/bash + +function load_packages() +{ + GPMI PkgLoad "pcb-rnd-gpmi/actions" 0 + GPMI PkgLoad "pcb-rnd-gpmi/dialogs" 0 +} + +function ev_action() { + GPMI dialog_log "Hello world!\n" +} + +function main() +{ + load_packages + GPMI Bind "ACTE_action" "ev_action" + GPMI action_register "hello" "" "log hello world" "hello()" +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html (revision 13657) @@ -0,0 +1,25 @@ +Load packages the script depends on: +
              +
            • actions for registering the new action; +
            • dialogs for printing in the message log. +
            +

            +Create a function ev_action that will be called when any of +the actions registered by the script is executed. The script registers +only one action, so it does not need to check which action caused +the function to be called. +

            +When the action event is called, use dialog_log to append +a log message. +

            +In the "main" section of the script, bind event ACTE_action to +our local function ev_action - this gets ev_action to +be called when any of the actions registered by this script is executed. +

            +Finally use action_register to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps) +
            Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua (revision 13657) @@ -0,0 +1,9 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +function ev_action(id, name, argc, x, y) + dialog_log("Hello world!\n"); +end + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl (revision 13657) @@ -0,0 +1,10 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +sub ev_action { + my($id, $name, $argc, $x, $y) = @_; + dialog_log("Hello world!\n"); +} + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py (revision 13657) @@ -0,0 +1,8 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y): + dialog_log("Hello world!\n"); + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb (revision 13657) @@ -0,0 +1,9 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y) + dialog_log("Hello world!\n"); +end + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm (revision 13657) @@ -0,0 +1,9 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(define ev_action (lambda (id name argc x y) + (dialog_log "Hello world!\n"))) + +(Bind "ACTE_action" "ev_action") +(action_register "hello" "" "log hello world" "hello()") + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt (revision 13657) @@ -0,0 +1,10 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(defun ev_action (id name argc x y) + (dialog_log "Hello world!\n")) + +(Bind "ACTE_action" "ev_action") +(action_register "hello" "" "log hello world" "hello()") + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl (revision 13657) @@ -0,0 +1,10 @@ +PkgLoad pcb-rnd-gpmi/actions 0 +PkgLoad pcb-rnd-gpmi/dialogs 0 + +proc ev_action {id, name, argc, x, y} { + dialog_log "Hello world!\n" +} + +Bind ACTE_action ev_action +action_register "hello" "" "log hello world" "hello()" + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello/index.html (revision 13657) @@ -0,0 +1,63 @@ + + + + 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 + | +bash + | +lua + | +pl + | +py + | +rb + | +scm + | +stt + | +tcl +

            Explanation, step by step

            +Load packages the script depends on: +
              +
            • +actions + for registering the new action; +
            • +dialogs + for printing in the message log.
            + +

            Create a function +ev_action + that will be called when any of the actions registered by the script is executed. The script registers only one action, so it does not need to check which action caused the function to be called. +

            When the action event is called, use +dialog_log + to append a log message. +

            In the "main" section of the script, bind event +ACTE_action + to our local function +ev_action + - this gets +ev_action + to be called when any of the actions registered by this script is executed. +

            Finally use +action_register + to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps)
            + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc (revision 13657) @@ -0,0 +1,3 @@ +Create a new action hello() that prints "Hello world!" in a popup window. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name (revision 13657) @@ -0,0 +1 @@ +hello world (popup window) Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk (revision 13657) @@ -0,0 +1,14 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/actions", 0); + PkgLoad("pcb-rnd-gpmi/dialogs", 0); +} + +function ev_action(id, name, argc, x, y) +{ + dialog_report("Greeting window", "Hello world!"); +} + +BEGIN { + Bind("ACTE_action", "ev_action"); + action_register("hello", "", "log hello world", "hello()"); +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash (revision 13657) @@ -0,0 +1,18 @@ +#!/bin/bash + +function load_packages() +{ + GPMI PkgLoad "pcb-rnd-gpmi/actions" 0 + GPMI PkgLoad "pcb-rnd-gpmi/dialogs" 0 +} + +function ev_action() { + GPMI dialog_report "Greeting window" "Hello world!" +} + +function main() +{ + load_packages + GPMI Bind "ACTE_action" "ev_action" + GPMI action_register "hello" "" "log hello world" "hello()" +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html (revision 13657) @@ -0,0 +1,26 @@ +Load packages the script depends on: +
              +
            • actions for registering the new action; +
            • dialogs for creating a dialog box. +
            +

            +Create a function ev_action that will be called when any of +the actions registered by the script is executed. The script registers +only one action, so it does not need to check which action caused +the function to be called. +

            +When the action event is called, use dialog_report to pop +up a report dialog. First argument donates the name (title) of the window, +the second is the text printed in the window. +

            +In the "main" section of the script, bind event ACTE_action to +our local function ev_action - this gets ev_action to +be called when any of the actions registered by this script is executed. +

            +Finally use action_register to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps) +
            Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua (revision 13657) @@ -0,0 +1,9 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +function ev_action(id, name, argc, x, y) + dialog_report("Greeting window", "Hello world!"); +end + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl (revision 13657) @@ -0,0 +1,10 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +sub ev_action { + my($id, $name, $argc, $x, $y) = @_; + dialog_report("Greeting window", "Hello world!"); +} + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py (revision 13657) @@ -0,0 +1,8 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y): + dialog_report("Greeting window", "Hello world!"); + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb (revision 13657) @@ -0,0 +1,9 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y) + dialog_report("Greeting window", "Hello world!"); +end + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm (revision 13657) @@ -0,0 +1,9 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(define ev_action (lambda (id name argc x y) + (dialog_report "Greeting window" "Hello world!"))) + +(Bind "ACTE_action" "ev_action") +(action_register "hello" "" "log hello world" "hello()") + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt (revision 13657) @@ -0,0 +1,10 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(defun ev_action (id name argc x y) + (dialog_report "Greeting window" "Hello world!")) + +(Bind "ACTE_action" "ev_action") +(action_register "hello" "" "log hello world" "hello()") + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl (revision 13657) @@ -0,0 +1,10 @@ +PkgLoad pcb-rnd-gpmi/actions 0 +PkgLoad pcb-rnd-gpmi/dialogs 0 + +proc ev_action {id, name, argc, x, y} { + dialog_report "Greeting window" "Hello world!" +} + +Bind ACTE_action ev_action +action_register "hello" "" "log hello world" "hello()" + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html (revision 13657) @@ -0,0 +1,63 @@ + + + + pcb-rnd rosetta hello world (popup window) + + + + +<-- back to the index of Rosetta examples +

            hello world (popup window)

            +Create a new action hello() that prints "Hello world!" in a popup window. +

            Example implementations

            +awk + | +bash + | +lua + | +pl + | +py + | +rb + | +scm + | +stt + | +tcl +

            Explanation, step by step

            +Load packages the script depends on: +
              +
            • +actions + for registering the new action; +
            • +dialogs + for creating a dialog box.
            + +

            Create a function +ev_action + that will be called when any of the actions registered by the script is executed. The script registers only one action, so it does not need to check which action caused the function to be called. +

            When the action event is called, use +dialog_report + to pop up a report dialog. First argument donates the name (title) of the window, the second is the text printed in the window. +

            In the "main" section of the script, bind event +ACTE_action + to our local function +ev_action + - this gets +ev_action + to be called when any of the actions registered by this script is executed. +

            Finally use +action_register + to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps)
            + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc (revision 13657) @@ -0,0 +1,3 @@ +Create a new action hello() that prints "Hello world!" in a popup window, create a menu (under "Plugins/GPMI scripting/") that executes the action. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name (revision 13657) @@ -0,0 +1 @@ +hello world (popup window + submenu) Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk (revision 13657) @@ -0,0 +1,20 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/actions", 0); + PkgLoad("pcb-rnd-gpmi/dialogs", 0); +} + +function ev_action(id, name, argc, x, y) +{ + dialog_report("Greeting window", "Hello world!"); +} + +function ev_gui_init(id, argc, argv) +{ + create_menu("/main_menu/Plugins/GPMI scripting/hello", "hello()", "h", "Ctrlw", "tooltip for hello"); +} + +BEGIN { + Bind("ACTE_action", "ev_action"); + Bind("ACTE_gui_init", "ev_gui_init"); + action_register("hello", "", "log hello world", "hello()"); +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash (revision 13657) @@ -0,0 +1,24 @@ +#!/bin/bash + +function load_packages() +{ + GPMI PkgLoad "pcb-rnd-gpmi/actions" 0 + GPMI PkgLoad "pcb-rnd-gpmi/dialogs" 0 +} + +function ev_action() { + GPMI dialog_report "Greeting window" "Hello world!" +} + +function ev_gui_init() +{ + GPMI create_menu "/main_menu/Plugins/GPMI scripting/hello" "hello()" "h" "Ctrlw" "tooltip for hello" +} + +function main() +{ + load_packages + GPMI Bind "ACTE_action" "ev_action" + GPMI Bind "ACTE_gui_init" "ev_gui_init" + GPMI action_register "hello" "" "log hello world" "hello()" +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html (revision 13657) @@ -0,0 +1,33 @@ +Load packages the script depends on: +
              +
            • actions for registering the new action; +
            • dialogs for creating a dialog box. +
            +

            +Create a function ev_action that will be called when any of +the actions registered by the script is executed. The script registers +only one action, so it does not need to check which action caused +the function to be called. +

            +When the action event is called, use dialog_report to pop +up a report dialog. First argument donates the name (title) of the window, +the second is the text printed in the window. +

            +Create a function ev_gui_init that will be called when the +gui has been initialized - this is the right moment to register +new menus in the GUI. Put the new menu item in the +"Plugins/GPMI scripting/" menu by convention, and set hot key to ctrl+w. +The menu should execute action hello(). +

            +In the "main" section of the script, bind event ACTE_action to +our local function ev_action - this gets ev_action to +be called when any of the actions registered by this script is executed. +Also bind ev_gui_init so that the new menu can be safely created. +

            +Finally use action_register to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps) +
            Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua (revision 13657) @@ -0,0 +1,14 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +function ev_action(id, name, argc, x, y) + dialog_report("Greeting window", "Hello world!"); +end + +function ev_gui_init(id, argc, argv) + create_menu("/main_menu/Plugins/GPMI scripting/hello", "hello()", "h", "Ctrlw", "tooltip for hello"); +end + +Bind("ACTE_action", "ev_action"); +Bind("ACTE_gui_init", "ev_gui_init"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl (revision 13657) @@ -0,0 +1,17 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +sub ev_action { + my($id, $name, $argc, $x, $y) = @_; + dialog_report("Greeting window", "Hello world!"); +} + +sub ev_gui_init +{ + my($id, $name, $argc, $argv) = @_; + create_menu("/main_menu/Plugins/GPMI scripting/hello", "hello()", "h", "Ctrlw", "tooltip for hello"); +} + +Bind("ACTE_action", "ev_action"); +Bind("ACTE_gui_init", "ev_gui_init"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py (revision 13657) @@ -0,0 +1,12 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y): + dialog_report("Greeting window", "Hello world!"); + +def ev_gui_init(id, argc, argv): + create_menu("/main_menu/Plugins/GPMI scripting/hello", "hello()", "h", "Ctrlw", "tooltip for hello"); + +Bind("ACTE_action", "ev_action"); +Bind("ACTE_gui_init", "ev_gui_init"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb (revision 13657) @@ -0,0 +1,14 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/dialogs", 0); + +def ev_action(id, name, argc, x, y) + dialog_report("Greeting window", "Hello world!"); +end + +def ev_gui_init(id, argc, argv) + create_menu("/main_menu/Plugins/GPMI scripting/hello", "hello()", "h", "Ctrlw", "tooltip for hello"); +end + +Bind("ACTE_action", "ev_action"); +Bind("ACTE_gui_init", "ev_gui_init"); +action_register("hello", "", "log hello world", "hello()"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm (revision 13657) @@ -0,0 +1,12 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(define ev_action (lambda (id name argc x y) + (dialog_report "Greeting window" "Hello world!"))) + +(define ev_gui_init (lambda (id argc argv) + (create_menu "/main_menu/Plugins/GPMI scripting/hello" "hello()" "h" "Ctrlw" "tooltip for hello"))) + +(Bind "ACTE_action" "ev_action") +(Bind "ACTE_gui_init" "ev_gui_init") +(action_register "hello" "" "log hello world" "hello()") Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt (revision 13657) @@ -0,0 +1,12 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/dialogs" 0) + +(defun ev_action (id name argc x y) + (dialog_report "Greeting window" "Hello world!")) + +(defun ev_gui_init (id argc argv) + (create_menu "/main_menu/Plugins/GPMI scripting/hello" "hello()" "h" "Ctrlw" "tooltip for hello")) + +(Bind "ACTE_action" "ev_action") +(Bind "ACTE_gui_init" "ev_gui_init") +(action_register "hello" "" "log hello world" "hello()") Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl (revision 13657) @@ -0,0 +1,15 @@ +PkgLoad pcb-rnd-gpmi/actions 0 +PkgLoad pcb-rnd-gpmi/dialogs 0 + +proc ev_action {id, name, argc, x, y} { + dialog_report "Greeting window" "Hello world!" +} + +proc ev_gui_init {id, argc, argv} { + create_menu "/main_menu/Plugins/GPMI scripting/hello" "hello()" "h" "Ctrlw" "tooltip for hello" +} + +Bind ACTE_action ev_action +Bind ACTE_gui_init ev_gui_init +action_register "hello" "" "log hello world" "hello()" + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html (revision 13657) @@ -0,0 +1,66 @@ + + + + pcb-rnd rosetta hello world (popup window + submenu) + + + + +<-- back to the index of Rosetta examples +

            hello world (popup window + submenu)

            +Create a new action hello() that prints "Hello world!" in a popup window, create a menu (under "Plugins/GPMI scripting/") that executes the action. +

            Example implementations

            +awk + | +bash + | +lua + | +pl + | +py + | +rb + | +scm + | +stt + | +tcl +

            Explanation, step by step

            +Load packages the script depends on: +
              +
            • +actions + for registering the new action; +
            • +dialogs + for creating a dialog box.
            + +

            Create a function +ev_action + that will be called when any of the actions registered by the script is executed. The script registers only one action, so it does not need to check which action caused the function to be called. +

            When the action event is called, use +dialog_report + to pop up a report dialog. First argument donates the name (title) of the window, the second is the text printed in the window. +

            Create a function +ev_gui_init + that will be called when the gui has been initialized - this is the right moment to register new menus in the GUI. Put the new menu item in the "Plugins/GPMI scripting/" menu by convention, and set hot key to ctrl+w. The menu should execute action hello(). +

            In the "main" section of the script, bind event +ACTE_action + to our local function +ev_action + - this gets +ev_action + to be called when any of the actions registered by this script is executed. Also bind ev_gui_init so that the new menu can be safely created. +

            Finally use +action_register + to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps)
            + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc (revision 13657) @@ -0,0 +1,3 @@ +Create a new action mv(dx,dy) that moves selected objects relative by dx and dy mm. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ID.name (revision 13657) @@ -0,0 +1 @@ +action: move selected objects Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk (revision 13657) @@ -0,0 +1,22 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/actions", 0); + PkgLoad("pcb-rnd-gpmi/layout", 0); +} + +function ev_action(id, name, argc, x, y ,dx,dy,n,num_objs,obj_ptr) +{ + dx = action_arg(0) * mm2pcb_multiplier() + dy = action_arg(1) * mm2pcb_multiplier() + + num_objs = layout_search_selected("mv_search", "OM_ANY") + for(n = 0; n < num_objs; n++) { + obj_ptr = layout_search_get("mv_search", n) + layout_obj_move(obj_ptr, "OC_OBJ", dx, dy) + } + layout_search_free("mv_search") +} + +BEGIN { + Bind("ACTE_action", "ev_action"); + action_register("mv", "", "move selected objects by dx and dy mm", "mv(dx,dy)"); +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash (revision 13657) @@ -0,0 +1,41 @@ +#!/bin/bash + +function load_packages() +{ + GPMI PkgLoad "pcb-rnd-gpmi/actions" 0 + GPMI PkgLoad "pcb-rnd-gpmi/layout" 0 +} + +function ev_action() { + local dx dy n num_objs + + GPMI action_arg 0 + a0=`bash_int "$result"` + + GPMI action_arg 1 + a1=`bash_int "$result"` + + GPMI mm2pcb_multiplier + conv=`bash_int "$result"` + + dx=$(($a0 * $conv)) + dy=$(($a1 * $conv)) + + GPMI layout_search_selected "mv_search" "OM_ANY" + num_objs=`bash_int "$result"` + + for n in `seq 0 $(($num_objs-1))` + do + GPMI layout_search_get "mv_search" $n + obj_ptr="$result" + GPMI layout_obj_move $obj_ptr "OC_OBJ" $dx $dy + done + GPMI layout_search_free "mv_search" +} + +function main() +{ + load_packages + GPMI Bind "ACTE_action" "ev_action" + GPMI action_register "mv" "" "move selected objects by dx and dy mm" "mv(dx,dy)" +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.html (revision 13657) @@ -0,0 +1,36 @@ +Load packages the script depends on: +
              +
            • actions for registering the new action; +
            • layout for searching selected objects and moving objects. +
            +

            +Create a function ev_action that will be called when any of +the actions registered by the script is executed. The script registers +only one action, so it does not need to check which action caused +the function to be called. +

            +When the action event is called, first set up: +

              +
            • fetch event argument 0 and 1 using action_arg; +
            • resolve the conversion rate from mm to PCB's units using mm2pcb_multiplier; +
            • perform a search for all selected object using layout_search_selected (return value is the number of objects found), name the resulting list "mv_search" +
            +A loop then iterates over the objects on the list: +
              +
            • resolve the Nth element of the list using layout_search_get, referencing the list by name ("mv_search") and specifying which element to get (the Nth); the result is an object pointer; +
            • move the object using layout_obj_move; specify the object pointer, then which part of the object should be moved ("OC_OBJ" means the whole object) and relative offsets (dx and dy calculated earlier) +
            +Finally the search list shall be destroyed to reclaim memory, using layout_search_free. +

            + +In the "main" section of the script, bind event ACTE_action to +our local function ev_action - this gets ev_action to +be called when any of the actions registered by this script is executed. +

            +Finally use action_register to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps) +
            Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua (revision 13657) @@ -0,0 +1,18 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/layout", 0); + +function ev_action(id, name, argc, x, y) + local dx = action_arg(0) * mm2pcb_multiplier() + local dy = action_arg(1) * mm2pcb_multiplier() + + local num_objs = layout_search_selected("mv_search", "OM_ANY") + for n=0,num_objs+1 + do + obj_ptr = layout_search_get("mv_search", n) + layout_obj_move(obj_ptr, "OC_OBJ", dx, dy) + end + layout_search_free("mv_search") +end + +Bind("ACTE_action", "ev_action"); +action_register("mv", "", "move selected objects by dx and dy mm", "mv(dx,dy)"); \ No newline at end of file Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl (revision 13657) @@ -0,0 +1,20 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/layout", 0); + +sub ev_action { + my($id, $name, $argc, $x, $y) = @_; + + my $dx = action_arg(0) * mm2pcb_multiplier(); + my $dy = action_arg(1) * mm2pcb_multiplier(); + + my $num_objs = layout_search_selected("mv_search", "OM_ANY"); + for(my $n = 0; $n < $num_objs; $n++) { + $obj_ptr = layout_search_get("mv_search", $n); + layout_obj_move($obj_ptr, "OC_OBJ", $dx, $dy); + } + layout_search_free("mv_search"); + +} + +Bind("ACTE_action", "ev_action"); +action_register("mv", "", "move selected objects by dx and dy mm", "mv(dx,dy)"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.py =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.py (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.py (revision 13657) @@ -0,0 +1,15 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/layout", 0); + +def ev_action(id, name, argc, x, y): + dx = int(action_arg(0)) * float(mm2pcb_multiplier()) + dy = int(action_arg(1)) * float(mm2pcb_multiplier()) + num_objs = int(layout_search_selected("mv_search", "OM_ANY")) + for n in xrange(0, num_objs): + obj_ptr = layout_search_get("mv_search", n) + layout_obj_move(obj_ptr, "OC_OBJ", dx, dy) + layout_search_free("mv_search") + +Bind("ACTE_action", "ev_action"); +action_register("hello", "", "log hello world", "hello()"); +action_register("mv", "", "move selected objects by dx and dy mm", "mv(dx,dy)"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb (revision 13657) @@ -0,0 +1,25 @@ +PkgLoad("pcb-rnd-gpmi/actions", 0); +PkgLoad("pcb-rnd-gpmi/layout", 0); + +def ev_action(id, name, argc, x, y) +# TODO: how to convert 1e+06 in ruby? +# conv = mm2pcb_multiplier().to_i + conv = 1000000 + + + dx = action_arg(0).to_i * conv.to_i; + dy = action_arg(1).to_i * conv.to_i; + + num_objs = layout_search_selected("mv_search", "OM_ANY").to_i; + + for n in 0..(num_objs-1) + obj_ptr = layout_search_get("mv_search", n); + layout_obj_move(obj_ptr, "OC_OBJ", dx, dy); + n += 1; + end + layout_search_free("mv_search"); + +end + +Bind("ACTE_action", "ev_action"); +action_register("mv", "", "move selected objects by dx and dy mm", "mv(dx,dy)"); Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm (revision 13657) @@ -0,0 +1,20 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/layout" 0) + +(define ev_action (lambda (id name argc x y) +(let + ( + (dx (* (string->number (action_arg 0)) (string->number (mm2pcb_multiplier)))) + (dy (* (string->number (action_arg 1)) (string->number (mm2pcb_multiplier)))) + (num_objs (string->number (layout_search_selected "mv_search" "OM_ANY"))) + (obj_ptr 0) + ) + (do ((n 0 (1+ n))) + ((> n num_objs)) + (set! obj_ptr (layout_search_get "mv_search" n)) + (layout_obj_move obj_ptr "OC_OBJ" (inexact->exact dx) (inexact->exact dy)) + ) +))) + +(Bind "ACTE_action" "ev_action") +(action_register "mv" "" "move selected objects by dx and dy mm" "mv(dx,dy)") Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt (revision 13657) @@ -0,0 +1,24 @@ +(PkgLoad "pcb-rnd-gpmi/actions" 0) +(PkgLoad "pcb-rnd-gpmi/layout" 0) + +(defun ev_action (id name argc x y) +(let + ( + (dx (* (->num (action_arg 0)) (->num (mm2pcb_multiplier)))) + (dy (* (->num (action_arg 1)) (->num (mm2pcb_multiplier)))) + (num_objs (->num (layout_search_selected "mv_search" "OM_ANY"))) + (obj_ptr 0) + ) + (do ((n 0 (1+ n))) + ((> n num_objs)) + (set! obj_ptr (layout_search_get "mv_search" n)) + (layout_obj_move obj_ptr "OC_OBJ" (->int dx) (->int dy)) + ) +) +) + +(Bind "ACTE_action" "ev_action") +(action_register "mv" "" "move selected objects by dx and dy mm" "mv(dx,dy)") + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl (revision 13657) @@ -0,0 +1,17 @@ +PkgLoad pcb-rnd-gpmi/actions 0 +PkgLoad pcb-rnd-gpmi/layout 0 + +proc ev_action {id, name, argc, x, y} { + set dx [expr round([action_arg 0] * [mm2pcb_multiplier])] + set dy [expr round([action_arg 1] * [mm2pcb_multiplier])] + + set num_objs [layout_search_selected mv_search OM_ANY] + for {set n 0} {$n < $num_objs} {incr n} { + set obj_ptr [layout_search_get mv_search $n] + layout_obj_move $obj_ptr OC_OBJ $dx $dy + } + layout_search_free mv_search +} + +Bind ACTE_action ev_action +action_register "mv" "" "move selected objects by dx and dy mm" "mv(dx,dy)" Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/30_move/index.html (revision 13657) @@ -0,0 +1,82 @@ + + + + pcb-rnd rosetta action: move selected objects + + + + +<-- back to the index of Rosetta examples +

            action: move selected objects

            +Create a new action mv(dx,dy) that moves selected objects relative by dx and dy mm. +

            Example implementations

            +awk + | +bash + | +lua + | +pl + | +py + | +rb + | +scm + | +stt + | +tcl +

            Explanation, step by step

            +Load packages the script depends on: +
              +
            • +actions + for registering the new action; +
            • +layout + for searching selected objects and moving objects.
            + +

            Create a function +ev_action + that will be called when any of the actions registered by the script is executed. The script registers only one action, so it does not need to check which action caused the function to be called. +

            When the action event is called, first set up: +

              +
            • fetch event argument 0 and 1 using +action_arg +; +
            • resolve the conversion rate from mm to PCB's units using +mm2pcb_multiplier +; +
            • perform a search for all selected object using +layout_search_selected + (return value is the number of objects found), name the resulting list "mv_search"
            + A loop then iterates over the objects on the list: +
              +
            • resolve the Nth element of the list using +layout_search_get +, referencing the list by name ("mv_search") and specifying which element to get (the Nth); the result is an object pointer; +
            • move the object using +layout_obj_move +; specify the object pointer, then which part of the object should be moved ("OC_OBJ" means the whole object) and relative offsets (dx and dy calculated earlier)
            + Finally the search list shall be destroyed to reclaim memory, using +layout_search_free +. +

            In the "main" section of the script, bind event +ACTE_action + to our local function +ev_action + - this gets +ev_action + to be called when any of the actions registered by this script is executed. +

            Finally use +action_register + to register the action: +

              +
            • first argument is the name of the action +
            • second is the xy query string; it is empty since this action won't need coordinates to operate on +
            • third is the description that shows up in dumps and helps +
            • fourth is the syntax description (also for helps)
            + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc (revision 13657) @@ -0,0 +1 @@ +Create a new exporter that prints a list of drills in x,y,dia table in CSV, TSV or text format Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name (revision 13657) @@ -0,0 +1 @@ +drill list exporter Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk (revision 13657) @@ -0,0 +1,60 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/hid", 0) + PkgLoad("pcb-rnd-gpmi/layout", 0) + PkgLoad("pcb-rnd-gpmi/dialogs", 0) + + hid = hid_create("drill", "drill list export") + attr_path = hid_add_attribute(hid, "filename", "name of the output file", "HIDA_Path", 0, 0, "drill.txt") + attr_format = hid_add_attribute(hid, "format", "file format", "HIDA_Enum", 0, 0, "CSV|TSV|text") + hid_register(hid) + + fmt = 0 + conv = mm2pcb_multiplier() + channel = "" + green_light = 0 +} + +function make_gc(event_id, hid, gc) { + if (channel == "") { + channel = hid_get_attribute(hid, attr_path) +# awk: can't check whether the file can be open here + fmt = hid_get_attribute(hid, attr_format) + } +} + +function destroy_gc(event_id, hid, gc) { + if (channel != "") { + close(channel) + channel = "" + } +} + +function set_layer(event_id, hid, group, layer, flags, empty) { + if ((layer_flag_is_set(flags, "LYT_ASSY") == "1") && (layer_flag_is_set(flags, "LYT_TOP") == "1")) + green_light = 1 + else + green_light = 0 +} + +function fill_circle(event_id, hid, gc, cx, cy, r ,dia) { + if (green_light) { + cx = cx / conv + cy = cy / conv + dia = r / conv * 2 + + if (fmt == "CSV") { + print cx "," cy "," dia > channel + } else if (fmt == "TSV") { + print cx "\t" cy "\t" dia > channel + } else if (fmt == "text") { + print cx " " cy " " dia > channel + } + } +} + +BEGIN { + Bind("HIDE_make_gc", "make_gc") + Bind("HIDE_destroy_gc", "destroy_gc") + Bind("HIDE_set_layer_group", "set_layer_group") + Bind("HIDE_fill_circle", "fill_circle") +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html (revision 13657) @@ -0,0 +1,60 @@ + +An exporter is a hid registered. During the export +process, pcb-rnd calls the exporter to draw objects on layers. The GPMI +layer converts these calls to bindable events. An exporter script catches +the drawing events relevant to the output format and draws everything from +event handlers. +

            +An exporter is sort of a drawing backend: pcb-rnd sets up graphic contexts +(gc for short) and draws on them. The first gc set up should open the +output file, the last gc closed should flush/close the file. +

            +


            + +

            Theory of operation

            +Assume only filled circles on the +top assembly layer are holes. Emit a line for each of these +and ignore everything else. + +

            Implementation

            +Load packages the script depends on: +
              +
            • hid for registering the new exporter; +
            • layout for unit conversion; +
            • dialogs for error reporting. +
            +

            +Set up an exporter hid, storing the handle of each object created in +a global variable: +

              +
            • create a hid using hid_create +
            • add two attributes (fields) to the dialog using hid_add_attribute +
            • register the new hid using hid_register - this makes it an exporter +
            +

            +Set up global state variables: +

              +
            • fmt will be a cache for the format selected by the user +
            • conv is the conversion scale between mm and PCB internal coordinate unit +
            • channel specifies a file handle or indicates that the output file is open +
            • green_light indicates that the exporter is drawing the relevant layer +
            +

            +Define a make_gc callback. It is called when a new graphic +context is created (e.g. for layers). An exporter is sort of a drawing +backend: pcb-rnd sets up gc's and draws on them. The first gc set up +should open the output file, the last gc closed should flush/close the file. +Define a destroy_gc callback for the latter. GCs are +destroyed at the end of the export process. Use global variable channel +to make sure the file is open/close only once (see TODO script context). +

            +Define a set_layer callback that sets green_light to true if +layer name is "topasssembly", false otherwise. +

            +Callback fill_circle is the workhorse: check if we have the green +light to emit lines, then convert coordinates and diameter to mm and +decide what format to use for printing a line for each filled circle. +

            +Finally, bind all four callbacks to exporter events. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua (revision 13657) @@ -0,0 +1,65 @@ +PkgLoad("pcb-rnd-gpmi/hid", 0) +PkgLoad("pcb-rnd-gpmi/layout", 0) +PkgLoad("pcb-rnd-gpmi/dialogs", 0) + +hid = hid_create("drill", "drill list export") +attr_path = hid_add_attribute(hid, "filename", "name of the output file", "HIDA_Path", 0, 0, "drill.txt") +attr_format = hid_add_attribute(hid, "format", "file format", "HIDA_Enum", 0, 0, "CSV|TSV|text") +hid_register(hid) + +fmt = 0 +conv = mm2pcb_multiplier() +channel = nil +green_light = 0 + +function make_gc(event_id, hid, gc) + if channel == nil + then + channel = io.open(hid_get_attribute(hid, attr_path), "w") + if channel == nil + then + dialog_report("Error exporting drill", "Could not open file [hid_get_attribute $hid $attr_path] for\nwriting, exporting drill failed.") + return + end + fmt = hid_get_attribute(hid, attr_format) + end +end + +function destroy_gc(event_id, hid, gc) + if channel ~= nil + then + channel:close() + channel = nil + end +end + +function set_layer_group(event_id, hid, group, layer, flags, empty) + if (layer_flag_is_set(flags, "LYT_ASSY") == "1") and (layer_flag_is_set(flags, "LYT_TOP") == "1") + then + green_light = 1 + else + green_light = 0 + end +end + +function fill_circle(event_id, hid, gc, cx, cy, r) + if green_light == 1 + then + cx = cx / conv + cy = cy / conv + local dia = r / conv * 2 + + if fmt == "CSV" then + channel:write(cx .. "," .. cy .. "," .. dia .. "\n") + elseif (fmt == "TSV") then + channel:write(cx .. "\t" .. cy .. "\t" .. dia .. "\n") + elseif (fmt == "text") then + channel:write(cx .. " " .. cy .. " " .. dia .. "\n") + end + end +end + +Bind("HIDE_make_gc", "make_gc") +Bind("HIDE_destroy_gc", "destroy_gc") +Bind("HIDE_set_layer_group", "set_layer_group") +Bind("HIDE_fill_circle", "fill_circle") Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl (revision 13657) @@ -0,0 +1,65 @@ +PkgLoad pcb-rnd-gpmi/hid 0 +PkgLoad pcb-rnd-gpmi/layout 0 +PkgLoad pcb-rnd-gpmi/dialogs 0 + +set hid [hid_create "drill" "drill list export"] +set attr_path [hid_add_attribute $hid "filename" "name of the output file" "HIDA_Path" 0 0 "drill.txt"] +set attr_format [hid_add_attribute $hid "format" "file format" "HIDA_Enum" 0 0 "CSV|TSV|text"] +hid_register $hid + +set fmt 0 +set conv [mm2pcb_multiplier] +set channel -1 +set green_light 0 + +proc make_gc {event_id hid gc} { + global channel attr_path attr_format fmt + + if {$channel == -1} { + if {[catch {open [hid_get_attribute $hid $attr_path] "w"} channel]} { + dialog_report "Error exporting drill" "Could not open file [hid_get_attribute $hid $attr_path] for\nwriting, exporting drill failed." + return + } + set fmt [hid_get_attribute $hid $attr_format] + } +} + +proc destroy_gc {event_id hid gc} { + global channel + + if {$channel > -1} { + close $channel + set channel -1 + } +} + +proc set_layer_group {event_id hid group layer flags empty} { + global green_light + + if { [layer_flag_is_set $flags "LYT_ASSY"] && [layer_flag_is_set $flags "LYT_TOP"] } { set green_light 1; puts "!!!!!!!!!!!!!!!"} { set green_light 0 } +} + +proc fill_circle {event_id hid gc cx cy r} { + global channel conv fmt green_light + + if {$green_light} { + set cx [expr $cx / $conv] + set cy [expr $cy / $conv] + set dia [expr $r / $conv * 2] + + if {$fmt eq "CSV"} { + puts $channel "$cx,$cy,$dia" + } elseif {$fmt eq "TSV"} { + puts $channel "$cx $cy $dia" + } elseif {$fmt eq "text"} { + puts $channel "$cx $cy $dia" + } + } +} + +Bind HIDE_make_gc make_gc +Bind HIDE_destroy_gc destroy_gc +Bind HIDE_set_layer_group set_layer_group +Bind HIDE_fill_circle fill_circle + +puts "NA?" Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html (revision 13657) @@ -0,0 +1,79 @@ + + + + pcb-rnd rosetta drill list exporter + + + + +<-- back to the index of Rosetta examples +

            drill list exporter

            +Create a new exporter that prints a list of drills in x,y,dia table in CSV, TSV or text format +

            Example implementations

            +awk + | +lua + | +tcl +

            Explanation, step by step

            + + An exporter is a hid registered. During the export process, pcb-rnd calls the exporter to draw objects on layers. The GPMI layer converts these calls to bindable events. An exporter script catches the drawing events relevant to the output format and draws everything from event handlers. +

            An exporter is sort of a drawing backend: pcb-rnd sets up graphic contexts (gc for short) and draws on them. The first gc set up should open the output file, the last gc closed should flush/close the file. +

            +


            +

            Theory of operation

            + Assume only +filled circles + on the +top assembly layer + are holes. Emit a line for each of these and ignore everything else. +

            Implementation

            + Load packages the script depends on: +
              +
            • +hid + for registering the new exporter; +
            • +layout + for unit conversion; +
            • +dialogs + for error reporting.
            + +

            Set up an exporter hid, storing the handle of each object created in a global variable: +

            + +

            Set up global state variables: +

              +
            • fmt will be a cache for the format selected by the user +
            • conv is the conversion scale between mm and PCB internal coordinate unit +
            • channel specifies a file handle or indicates that the output file is open +
            • green_light indicates that the exporter is drawing the relevant layer
            + +

            Define a +make_gc + callback. It is called when a new graphic context is created (e.g. for layers). An exporter is sort of a drawing backend: pcb-rnd sets up gc's and draws on them. The first gc set up should open the output file, the last gc closed should flush/close the file. Define a +destroy_gc + callback for the latter. GCs are destroyed at the end of the export process. Use global variable +channel + to make sure the file is open/close only once (see TODO +script context +). +

            Define a +set_layer + callback that sets green_light to true if layer name is "topasssembly", false otherwise. +

            Callback +fill_circle + is the workhorse: check if we have the green light to emit lines, then convert coordinates and diameter to mm and decide what format to use for printing a line for each filled circle. +

            Finally, bind all four callbacks to exporter events. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc (revision 13657) @@ -0,0 +1 @@ +Create and animate an analog clock on a dedicated UI layer. Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name (revision 13657) @@ -0,0 +1 @@ +animated clock on a UI layer Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk (revision 13657) @@ -0,0 +1,126 @@ +BEGIN { + PkgLoad("pcb-rnd-gpmi/actions", 0); + PkgLoad("pcb-rnd-gpmi/dialogs", 0); + PkgLoad("pcb-rnd-gpmi/layout", 0); + pi=3.141592654 +} + +# the clock coordinate system +function clock_cos(a) +{ + return cos((a-15)*6/180*pi) +} +function clock_sin(a) +{ + return sin((a-15)*6/180*pi) +} + +# draw the labels +function draw_dial(ui, cx, cy, r ,flg,w,cl,a,l,x1,y1,x2,y2) +{ + flg = "FL_NONE" + w = int(0.5 * mm) + cl = int(1 * mm) + + for(a = 0; a < 60; a++) { + tw = w + if (a == 0) + l = 4*mm + else if (a % 5 == 0) + l = 2*mm + else { + l = 1*mm + tw = w / 2 + } + + x1 = int(cx + clock_cos(a) * r) + y1 = int(cy + clock_sin(a) * r) + x2 = int(cx + clock_cos(a) * (r-l)) + y2 = int(cy + clock_sin(a) * (r-l)) + layout_create_line("", ui, x1, y1, x2, y2, tw, cl, flg) + + + if ((a % 5) == 0) { + x2 = int(cx + clock_cos(a) * (r-6*mm)) - 0.25*mm + y2 = int(cy + clock_sin(a) * (r-6*mm)) + layout_create_text("", ui, x2, y2, 0, 100, ((a == 0) ? "12" : a/5), flg) + } + } + + hlen[0] = 0.95 + hlen[1] = 0.9 + hlen[2] = 0.6 + + x2 = int(cx + clock_cos(a) * (r * hlen[0])) + y2 = int(cy + clock_sin(a) * (r * hlen[0])) + hand_sec = layout_create_line("hands", ui, cx, cy, x2, y2, 0.2*mm, cl, flg) + + x2 = int(cx + clock_cos(a) * (r * hlen[1])) + y2 = int(cy + clock_sin(a) * (r * hlen[1])) + hand_min = layout_create_line("hands", ui, cx, cy, x2, y2, 0.5*mm, cl, flg) + + x2 = int(cx + clock_cos(a) * (r * hlen[2])) + y2 = int(cy + clock_sin(a) * (r * hlen[2])) + hand_hour = layout_create_line("hands", ui, cx, cy, x2, y2, 2*mm, cl, flg) + + clock_cx = cx + clock_cy = cy + clock_r = r +} + + +function ev_action(id, name, argc, x, y) +{ + ui = int(uilayer_alloc("clock", "#DD33DD")) + mm = mm2pcb_multiplier(); + AddTimer(0, 10, "ev_second", ""); + draw_dial(ui, 50*mm, 50*mm, 30*mm) + + clock_sec = 12 + clock_min = 33 + clock_hour = 9 + set_hands() +} + +function set_hand(obj, idx, at ,ox2,oy2,x2,y2) +{ + ox2 = layout_obj_coord(obj, "OC_P2X") + oy2 = layout_obj_coord(obj, "OC_P2Y") + + x2 = int(clock_cx + clock_cos(at) * (clock_r * hlen[idx])) + y2 = int(clock_cy + clock_sin(at) * (clock_r * hlen[idx])) + + layout_obj_move(obj, "OC_P2", x2-ox2, y2-oy2); +} + +function set_hands() +{ + set_hand(hand_hour, 2, (clock_hour + clock_min/60 + clock_sec/3600)*5) + set_hand(hand_min, 1, clock_min + clock_sec/60) + set_hand(hand_sec, 0, clock_sec) +} + + +function ev_second(timer_data) +{ + if (hand_sec != "") { + clock_sec++; + if (clock_sec >= 60) { + clock_sec = 0 + clock_min++ + if (clock_min >= 60) { + clock_min = 0 + clock_hour++ + if (clock_hour >= 12) + clock_hour = 0; + } + } + set_hands() + } +} + +BEGIN { + layout_search_empty("hands") + Bind("ACTE_action", "ev_action"); + action_register("clock", "", "animate an analog clock on a debug layer", "clock()"); +} Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html (revision 13657) @@ -0,0 +1,49 @@ +Animated clock on an UI layer. +

            +


            + +

            Theory of operation

            + + +

            Implementation

            +Load packages the script depends on: +
              +
            • hid for registering the new exporter; +
            • layout for unit conversion; +
            • dialogs for error reporting. +
            +

            +Set up an exporter hid, storing the handle of each object created in +a global variable: +

              +
            • create a hid using hid_create +
            • add two attributes (fields) to the dialog using hid_add_attribute +
            • register the new hid using hid_register - this makes it an exporter +
            +

            +Set up global state variables: +

              +
            • fmt will be a cache for the format selected by the user +
            • conv is the conversion scale between mm and PCB internal coordinate unit +
            • channel specifies a file handle or indicates that the output file is open +
            • green_light indicates that the exporter is drawing the relevant layer +
            +

            +Define a make_gc callback. It is called when a new graphic +context is created (e.g. for layers). An exporter is sort of a drawing +backend: pcb-rnd sets up gc's and draws on them. The first gc set up +should open the output file, the last gc closed should flush/close the file. +Define a destroy_gc callback for the latter. GCs are +destroyed at the end of the export process. Use global variable channel +to make sure the file is open/close only once (see TODO script context). +

            +Define a set_layer callback that sets green_light to true if +layer name is "topasssembly", false otherwise. +

            +Callback fill_circle is the workhorse: check if we have the green +light to emit lines, then convert coordinates and diameter to mm and +decide what format to use for printing a line for each filled circle. +

            +Finally, bind all four callbacks to exporter events. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/90_clock/index.html (revision 13657) @@ -0,0 +1,69 @@ + + + + pcb-rnd rosetta animated clock on a UI layer + + + + +<-- back to the index of Rosetta examples +

            animated clock on a UI layer

            +Create and animate an analog clock on a dedicated UI layer. +

            Example implementations

            +awk +

            Explanation, step by step

            +Animated clock on an UI layer. +

            +


            +

            Theory of operation

            + +

            Implementation

            + Load packages the script depends on: +
              +
            • +hid + for registering the new exporter; +
            • +layout + for unit conversion; +
            • +dialogs + for error reporting.
            + +

            Set up an exporter hid, storing the handle of each object created in a global variable: +

            + +

            Set up global state variables: +

              +
            • fmt will be a cache for the format selected by the user +
            • conv is the conversion scale between mm and PCB internal coordinate unit +
            • channel specifies a file handle or indicates that the output file is open +
            • green_light indicates that the exporter is drawing the relevant layer
            + +

            Define a +make_gc + callback. It is called when a new graphic context is created (e.g. for layers). An exporter is sort of a drawing backend: pcb-rnd sets up gc's and draws on them. The first gc set up should open the output file, the last gc closed should flush/close the file. Define a +destroy_gc + callback for the latter. GCs are destroyed at the end of the export process. Use global variable +channel + to make sure the file is open/close only once (see TODO +script context +). +

            Define a +set_layer + callback that sets green_light to true if layer name is "topasssembly", false otherwise. +

            Callback +fill_circle + is the workhorse: check if we have the green light to emit lines, then convert coordinates and diameter to mm and decide what format to use for printing a line for each filled circle. +

            Finally, bind all four callbacks to exporter events. + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/Makefile =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/Makefile (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/Makefile (revision 13657) @@ -0,0 +1,4 @@ +all: FORCE + cd ../util && ./rosetta_genpages.sh + +FORCE: Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.html (revision 13657) @@ -0,0 +1,68 @@ + + + + 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 bash lua perl python ruby scheme stutter tcl + Create a new action hello() that prints "Hello world!" in the message log. +
            10 + hello world (popup window) + awk bash lua perl python ruby scheme stutter tcl + Create a new action hello() that prints "Hello world!" in a popup window. +
            12 + hello world (popup window + submenu) + awk bash lua perl python ruby scheme stutter tcl + Create a new action hello() that prints "Hello world!" in a popup window, create a menu (under "Plugins/GPMI scripting/") that executes the action. +
            30 + action: move selected objects + awk bash lua perl python ruby scheme stutter tcl + Create a new action mv(dx,dy) that moves selected objects relative by dx and dy mm. +
            35 + drill list exporter + awk lua tcl + Create a new exporter that prints a list of drills in x,y,dia table in CSV, TSV or text format +
            90 + animated clock on a UI layer + awk + Create and animate an analog clock on a dedicated UI layer. +
            + + + + Index: tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.templ.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.templ.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/rosetta/index.templ.html (revision 13657) @@ -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/1.2.7/doc/user/06_feature/gpmi/scripting_intro.html =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/scripting_intro.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/scripting_intro.html (revision 13657) @@ -0,0 +1,231 @@ + + + + pcb-rnd user manual + + + +

            Scripting intro

            +This document is an introduction to GPMI for pcb-rnd users. It focuses on +scripting pcb-rnd and doesn't discuss GPMI deeper than the minimum necessary. +GPMI is more generic than shown here. +

            +The scope of the document is to describe the relations between pcb-rnd, +hids, GPMI, glue packages and scripts. Details on how specific glue +packages access pcb-rnd internals (or how those internals work) are +described in other documents. + +

            1. pcb-rnd internals

            + +Since scripts are glued to pcb-rnd internals, scripters need to know +the basic concepts of how pcb-rnd is structured. + +

            1.1 pcb-rnd, HIDs, plugins and GPMI

            +pcb-rnd consists of: +
              +
            • a core that handles the file format, data structures, UI and exporter logics +
            • a hid system that is a layer between core and the HIDs +
            • a set of GUI HIDs which are responsible for interactive graphical display of the current design +
            • a set of exporter HIDs which are responsible for exporting offline representation of the current design +
            • a plugin system that can load HIDs from on the fly, from dynamic loadable libraries (.so or .dll) +
            • a buildin system which is the "static link" variant of the plugin system: some plugins can be selected to be statically linked into the pcb-rnd executable so they are "always loaded" +
            +

            +Note 1: at the moment GUI hids can not be plugins or buildins. +
            +Note 2: plugins/buildins are always exporter HIDs technically, but in practice +they do not have to offer exporting. This means such a HID plugin is loaded +and registered as an exporter on paper, but it doesn't really create a +new export facility, just sits there, interacting with pcb-rnd (creating +menus, actions, etc). Most script plugins do this. +

            +When the pcb-rnd executable is compiled, the core, the default GUI and exporter HIDs +and buildins are compiled into the executable. Later on +

            +The GPMI hid is an optional plugin that, by compile-time choice +of the user, can be: +

              +
            • left out all-together - pcb-rnd does not have scripting +
            • compiled as a plugin - when the .so (or .dll) is put in the right directory, pcb-rnd loads it during startup and has scripting +
            • compiled as buildin - becomes part of the pcb-rnd executable so that scripting is always available +
            + +

            1.2. Actions, menus, exporters

            +The core implements actions. An action is a command with custom arguments, +e.g. Delete(Selected). These actions are the commands on the default command +line in pcb-rnd. In batch mode the command language uses these actions as well. +Remote controlling pcb-rnd using the --listen switch will read these actions +on the standard input. +

            +GUI menus are configured to execute actions too. This also means it is impossible +to realize an user-accessible functionality that can be triggered from +the GUI command line, menu or batch input without making it an action. +

            +The only exception, where new functionality is not behind a new action is +exporters. An exporter is a structured dialog box of options and a set of +callback functions implementing a drawing API. Exporting works by the following +steps: +

              +
            1. An exporter HID may register one or more exporters. +
            2. When the user tries to export the design, pcb-rnd lists all + registered exporters. +
            3. The user chooses one, and the preconfigured dialog box + with the selected exporter's options are popped up. +
            4. pcb-rnd core runs the dialog and saves the results if the user + clicked on the ok button. +
            5. pcb-rnd starts the exporting process: it calls the callbacks + to draw the design layer by layer, object by object. +
            + +

            1.3. How a script can interact with the user

            +
              +
            • The script may register actions - these actions are instantly accessible from the GUI command line, on stdin with --listen and in batch mode +
            • The script may create menus and bind them to actions - when the menu is selected, the action is executed +
            • The script may bind to events that will be generated asynchronously by pcb-rnd - when such an event is received, the script executes some code +
            • The script may register new exporter(s) - the user will be able to export the design using the script +
            • The script may run arbitrary code "on load" (when the script is loaded) - however, that time the design or even the GUI may not be loaded/initialized yet - this is useful for registering actions, bind to events or set up exporters +
            + + +

            2. GPMI intro

            + +

            2.1. GPMI's place in the pcb-rnd world

            +
            +GPMI is a plugin/buildin HID. Instead of doing actual work, it loads scripts +and provides a glue layer between pcb-rnd and the scripts. The actual work +is performed by the scripts. +The glue layer comes in two kinds: +
              +
            • gpmi module: dynamic lib written in C, knows how to load and interpret a script and how to deliver events to the script +
            • gpmi package: dynamic lib, provides C functions the script can directly call; package functions then know how to deal with PCB internals +
            +Arrows drawn with dashed line represents a slow, string based communication. +
            [gpmi HID interacting with pcb-rnd and other components]
            + +

            2.2. Module, script, script context, packages

            +
            +Each time a script needs to be loaded, first a module is loaded and the name +of the script is passed to the module. During module initialization, the module +sets up a script interpreter and script context and loads the script into the +context. +

            +If there are 3 separate lua scripts running in pcb-rnd, there are 3 separate +lua modules loaded, each dealing with one of the scripts. The process of +loading a script is illustrated by highlighting the relevant paths with red +for step 1 and green for step 2. +

            +Step 0: the GPMI HID finds a script has to be loaded. The idea comes +from the config file (pcb-rnd-gpmi.conf) or from the GUI (manage scripts) +or as a request from a script already loaded. +

            +Step 1: the GPMI HID loads the corresponding module which in turns +loads the script. The script has a "main" part that is run on load. For +most languages this is the global code sections; in some languages it is +a specific function, usually called main. A few basic glue packages +are already loaded before the script. +

            +Step 2: the script can load glue packages. This usually happens +from the on-load main part from the script. The actual mechanism is to +call PkgLoad() from a glue package that was automatically loaded in +Step 1. The green arrows represent this path: the script executes PkgLoad() +which in turns loads other package(s) into the GPMI hid. +

            +Packages are loaded only once and are globally accessible for multiple modules. +

            [same diagram as before, with package load flow highlighted]
            + +

            2.3. Binding events, registering actions, creating menus

            +
            +Binding an event in a script is done by calling the Bind() function +(this is implemented in a package automatically loaded). The first +argument is the name of the event, the second argument is the name of +the script function that should be called when the event is triggered. Both +arguments are strings. The event binding mechanism is shown in red in the +map to the right. +

            +The script can create new actions using the action_register() function +(the actions package needs to be loaded first). A script may register multiple +actions. This call is marked with green in the above map. +If any of the actions registered by the script is called, the event "ACTE_action" +is generated. This has two implications: +

              +
            • a script that registers actions needs to bind the ACTE_action event to serve the action requests +
            • if a script registers multiple actions, in the event handler it needs to check which action triggered the event (e.g. with a switch()-like construction on the event name) +
            +
            [same diagram as before, with action registration flow highlighted]
            + +
            +Menus are created using the create_menu() call. Menus can be +created only when the GUI is already set up - this may happen only +after some of the scripts are already loaded. Thus scripts shall +create menus from an event handler bound to the ACTE_gui_init event. +This event is triggered right after the GUI has been set up. +On the map to the right the red arrows represent the path of ACTE_gui_init; +the green arrows represent the reaction of the script, creating the new +menu. +

            +

            [same diagram as before, with menu setup flow highlighted]
            + +

            2.4. Exporting

            +
            +Exporter scripts first have to set up an exporter hid. This typically +happens from their on-load main part. Related calls are in the hid +package. The following map shows this process with red arrows: +

            +When the user chooses to use the exporter, among the green arrows, +a series of events are triggered and the script can generate output +directly to a file from event handlers bound to these exporting events. +

            [same diagram as before, with exporter flow highlighted]
            + +

            2.5. Making modifications on the design

            +The purpose of a script might be to manipulate the objects in the current design. +Such a script registers actions, and implements the handler of the actions +using the layout package. The layout package provides calls to query, +change and create design objects. + + +

            3. How it works in practice

            + +

            3.1. Loading the GPMI plugin

            +Check the output of ./configure, it will tell if gpmi is compiled as buildin +or plugin (or not at all). +If the gpmi plugin is compiled as a buildin, it is already loaded, no +further steps are required. +

            +If gpmi is a plugin, gpmi_plugin.so (or gpmi_plugin.dll) needs to be +copied in one of the plugin directories pcb-rnd is looking into on startup: + +
            path purpose +
            +
            $prefix/lib/pcb-rnd/plugins/$arch/ system plugins, multihost +
            $prefix/lib/pcb-rnd/plugins/ system plugins +
            ~/.pcb/plugins/$arch/ user plugins, multihost +
            ~/.pcb/plugins/ user plugins +
            ./plugins/$arch/ project plugins, multihost +
            ./plugins/ project plugins +
            +In the above table: +

              +
            • $prefix is the installation prefix (normally /usr) +
            • $arch is the host arch triplet, e.g. i386-unknown-linux; this is useful if multiple architectures share the same NFS mounted plugin dir +
            • ~ is the user home directory, if exists, e.g. /home/jdoe +
            • ./ is the current working directory pcb has been started from; may be useful for project-local scripts +
            + +

            3.2. Loading scripts

            +The gpmi plugin looks for a file called "pcb-rnd-gpmi.conf" in each of the +plugin directories. Wherever the file is found, it is loaded and parsed. +The file is plain text, each line describes a script to be loaded. Empty +lines and lines starting with # are comments and are ignored. +

            +Script load lines contain two words separated by a space: a module name +and a script name. Relative paths in the the script name are relative to +the directory the config file is found in. +

            +Example config: +

            +# load the carc script (written in lua) from next to the config file:
            +lua carc.lua
            +
            +# load foo.awk, which is a mawk script, from its installation path
            +mawk /usr/lib/foo/foo.awk
            +
            Index: tags/1.2.7/doc/user/06_feature/gpmi/util/Makefile =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/util/Makefile (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/util/Makefile (revision 13657) @@ -0,0 +1 @@ +all: Index: tags/1.2.7/doc/user/06_feature/gpmi/util/rosetta_genpages.sh =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/util/rosetta_genpages.sh (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/util/rosetta_genpages.sh (revision 13657) @@ -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/1.2.7/doc/user/06_feature/gpmi/util/rosetta_genpages.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/gpmi/util/tags =================================================================== --- tags/1.2.7/doc/user/06_feature/gpmi/util/tags (nonexistent) +++ tags/1.2.7/doc/user/06_feature/gpmi/util/tags (revision 13657) @@ -0,0 +1,4 @@ +#!/bin/sh + +tr "\n" " " | sed "s@\(<[^/]\)@\n\1@g;s@\(]*>\)@\1\n@g" + Property changes on: tags/1.2.7/doc/user/06_feature/gpmi/util/tags ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/user/06_feature/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/index.html (revision 13657) @@ -0,0 +1,23 @@ + + + + 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/1.2.7/doc/user/06_feature/query/tutor_cli.html =================================================================== --- tags/1.2.7/doc/user/06_feature/query/tutor_cli.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/query/tutor_cli.html (revision 13657) @@ -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 elements 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/1.2.7/doc/user/06_feature/vendordrill/index.html =================================================================== --- tags/1.2.7/doc/user/06_feature/vendordrill/index.html (nonexistent) +++ tags/1.2.7/doc/user/06_feature/vendordrill/index.html (revision 13657) @@ -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 elements 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/1.2.7/doc/user/07_io/export_openscad/1206.scad =================================================================== --- tags/1.2.7/doc/user/07_io/export_openscad/1206.scad (nonexistent) +++ tags/1.2.7/doc/user/07_io/export_openscad/1206.scad (revision 13657) @@ -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/1.2.7/doc/user/07_io/export_openscad/preliminary.txt =================================================================== --- tags/1.2.7/doc/user/07_io/export_openscad/preliminary.txt (nonexistent) +++ tags/1.2.7/doc/user/07_io/export_openscad/preliminary.txt (revision 13657) @@ -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/1.2.7/doc/user/08_util/01_gsch2pcb-rnd.htm =================================================================== --- tags/1.2.7/doc/user/08_util/01_gsch2pcb-rnd.htm (nonexistent) +++ tags/1.2.7/doc/user/08_util/01_gsch2pcb-rnd.htm (revision 13657) @@ -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/1.2.7/doc/user/08_util/install_cgi.html =================================================================== --- tags/1.2.7/doc/user/08_util/install_cgi.html (nonexistent) +++ tags/1.2.7/doc/user/08_util/install_cgi.html (revision 13657) @@ -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/1.2.7/doc/user/09_appendix/action_reference.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/action_reference.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/action_reference.html (revision 13657) @@ -0,0 +1,578 @@ + + + + pcb-rnd user manual + + + + +

            +

            Pcb-rnd Action Reference

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            +pcb-rnd version 1.2.6, Revision: 13593 + +
            Action Description Syntax +
            ElementSetAttr Sets or clears an element-specific attribute.ElementSetAttr(refdes,name[,value])
            smartdisperse
            PasteBuffer Various 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(Save, Filename, [format], [force])
            ChangeDrillSize Changes the drilling hole size of objects.ChangeDrillSize(Object, delta|style)
            ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta|style)
            LoadhypFrom Loads the specified Hyperlynx file.LoadhypFrom(filename[, "debug"]...)
            SetOctagon Sets the octagon-flag of objects.SetOctagon(Object|ToggleObject|SelectedElements|Selected)
            aligntext Align Text ElementsAlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])
            Display Several display-related actions.Display(NameOnPCB|Description|Value|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)
            DeleteRats Delete rat lines.DeleteRats(AllRats|Selected|SelectedRats)
            Cursor Move the cursor.Cursor(Type,DeltaUp,DeltaRight,Units)
            dumpflags dump flags, optionally using the format string provided by the userdumpflags([fmt])
            ChkBuffer Return 1 if currently selected buffer's index matches idxChkBuffer(idx)
            ChkMode Return 1 if the currently selected mode is the expected_modeChkMode(expected_mode)
            netlist Perform various actions on netlists.Net(find|select|rats|norats|clear[,net[,pin]])
            Net(freeze|thaw|forcethaw)
            Net(swap)
            Net(add,net,pin)
            DebugXY Debug action, with coordinatesDebugXY(...)
            PadstackEdit interactive pad stack editorPadstackEdit(object)
            forcecolor change selected element's color to #RRGGBB, reset if does not start with '#'forcecolor(#RRGGBB)
            LoadFontFrom Load PCB font from a fileLoadFontFrom([file, id])
            LoadFrom Load layout data from a file.LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename[,format])
            ChangeAngle Changes 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)
            ToggleView Toggle the visibility of the specified layer or layer group.ToggleView(1..MAXLAYER)
            ToggleView(layername)
            ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)
            ToggleView(All, Open|Vis, Set|Clear|Toggle)
            DumpLibrary Display the entire contents of the libraries.DumpLibrary()
            CreateText Create a new text objectCreateText(layer, fontID, X, Y, direction, scale, text)
            MarkCrosshair Set/Reset the pcb_crosshair mark.MarkCrosshair()
            MarkCrosshair(Center)
            LoadTedaxFrom Loads the specified block from a tedax file. Type can be: netlist or footprint.LoadTedaxFrom(type, filename)
            MoveToCurrentLayer Moves objects to the current layer.MoveToCurrentLayer(Object|SelectedObjects)
            SetThermal Set the thermal (on the current layer) of pins or vias 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)
            propedit Run the property editorpropedit()
            PadstackConvert Convert selection or current buffer to padstackPadstackConvert(buffer|selected, [originx, originy])
            pscalib
            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.Editlayer([@layer], [name=text|auto=[0|1]|sub=[0|1])]
            Editlayer([@layer], attrib, key=value)
            SetFlag Sets flags on objects.SetFlag(Object|Selected|SelectedObjects, flag)
            SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)
            SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
            SetFlag(SelectedElements, flag)
            flag = square | octagon | thermal | join
            ClrFlag Clears flags on objects.ClrFlag(Object|Selected|SelectedObjects, flag)
            ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)
            ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
            ClrFlag(SelectedElements, flag)
            flag = square | octagon | thermal | join
            PrintUsage Print command line arguments of pcb-rnd or a plugin loaded.PrintUsage()
            PrintUsage(plugin)
            ClearSquare Clears the square-flag of pins and pads.ClearSquare(ToggleObject|SelectedElements|SelectedPins)
            ChangeHole Changes the hole flag of objects.ChangeHole(ToggleObject|Object|SelectedVias|Selected)
            conf Perform 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)
            Brave Changes brave settings.Brave()
            Brave(setting, on|off)
            distributetext Distribute Text ElementsDistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
            dlg_test test the attribute dialogdlg_test()
            DumpActions Dump all actions available.DumpActions()
            Attributes Let the user edit the attributes of the layout, current or given
            layer, or selected element or subcircuit.
            Attributes(Layout|Layer|Element|Subc)
            Attributes(Layer,layername)
            RenumberBlock
            ToggleHideName Toggles the visibility of element names.ToggleHideName(Object|SelectedElements)
            RenumberBuffer
            AutoRoute Auto-route some or all rat lines.AutoRoute(AllRats|SelectedRats)
            ReplaceFootprint Replace the footprint of the selected components with the footprint specified.ReplaceFootprint()
            net Perform various actions on netlists.Net(find|select|rats|norats|clear[,net[,pin]])
            Net(freeze|thaw|forcethaw)
            Net(swap)
            Net(add,net,pin)
            LoadFootprint Loads a single footprint by name.pcb_load_footprint(filename[,refdes,value])
            OptAutoOnly Toggles the optimize-only-autorouted flag.OptAutoOnly()
            New Starts a new layout.New([name])
            RipUp Ripup auto-routed tracks, or convert an element to parts.RipUp(All|Selected|Element)
            Import Import schematics.Import()
            Import([gnetlist|make[,source,source,...]])
            Import(setnewpoint[,(mark|center|X,Y)])
            Import(setdisperse,D,units)
            DumpCsect Print the cross-section of the board (layer stack)DumpCsect()
            Redo Redo recent "undo" operations.redo()
            Export Export the current layout, e.g. Export(png, --dpi, 600)Export(exporter, [exporter-args])
            FreeRotateBuffer 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.
            pcb_buffer_free_rotate([Angle])
            BoardFlip
            MoveLayer Moves/Creates/Deletes Layers.MoveLayer(old,new)
            LoadHpglFrom Loads the specified hpgl plot file to the current bufferLoadHpglFrom(filename)
            LibraryChanged Tells the GUI that the libraries have changed.LibraryChanged()
            CreateMenu Creates a new menu, popup (only path specified) or submenu (at least path and action are specified)CreateMenu(path | path, action, mnemonic, accel, tooltip, cookie)
            SavePatch Save netlist patch for back annotation.SavePatch(filename)
            ChkGridUnits Return 1 if currently selected grid unit matches the expected (normally mm or mil)ChkGridUnits(expected)
            mill Calculate toolpath for milling away coppermill()
            ChangeSquare Changes the square flag of pins and pads.ChangeSquare(ToggleObject)
            ChangeSquare(SelectedElements|SelectedPins)
            ChangeSquare(Selected|SelectedObjects)
            djopt Perform various optimizations on the current board.djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull)
            djopt(auto) - all of the above
            djopt(miter)
            PrintCopyright Print copyright notice.PrintCopyright()
            LoadLtspiceFrom Loads the specified ltspice .net and .asc file - the netlist must be mentor netlist.LoadLtspiceFrom(filename)
            extedit extedit(object|selected, [interactive|method])Invoke an external program to edit a specific part of the current board.
            DumpPlugins Print plugins loaded in a format digestable by scripts.DumpPlugins()
            SaveFontTo Save PCB font to a fileSaveFontTo([file, id])
            integrity perform integrirty check on the current board and generate errors if neededintegrity()
            ExecuteFile Run actions from the given file.ExecuteFile(filename)
            ChangePinName Sets the name of a specific pin on a specific element.ChangePinName(ElementName,PinNumber,PinName)
            RouteStyle Copies the indicated routing style into the current sizes.RouteStyle(1|2|3|4)
            SwitchHID Switch to another HID.SwitchHID(lesstif|gtk|batch)
            GlobalPuller Pull all traces tight.pcb_act_GlobalPuller()
            SetSquare sets the square-flag of objects.SetSquare(ToggleObject|SelectedElements|SelectedPins)
            Renumber Renumber all elements. The changes will be recorded to filename
            for use in backannotating these changes to the schematic.
            Renumber()
            Renumber(filename)
            SaveTedax Saves the specific type of data in a tEDAx file. Type can be: board-footprintsSaveTedax(type, filename)
            RouteStylesChanged Tells the GUI that the routing styles have changed.RouteStylesChanged()
            Polygon Some polygon related stuff.Polygon(Close|CloseHole|PreviousPoint)
            autocrop Autocrops the board dimensions to extants + marginautocrop()
            SelectLayer Select which layer is the current layer.SelectLayer(1..MAXLAYER|Silk|Rats)
            distribute Distribute ElementsDistribute(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])
            Connection Searches connections of the object at the cursor position.Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)
            query Perform various queries on PCB data.query(dump, expr) - dry run: compile and dump an expression
            ChangeFlag Sets 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 = square | octagon | thermal | join
            value = 0 | 1
            ListRotations
            Report Produce various report.Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])
            shape Interactive shape generator.shape()
            Bell Attempt to produce audible notification (e.g. beep the speaker).Bell()
            Undo Undo recent changes.undo()
            undo(ClearList)
            CycleDrag Cycle through which object is being draggedCycleDrag()
            EvalConf Perform 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 database
            PrintVersion Print version.PrintVersion()
            Teardrops
            FontEdit Convert the current font to a PCB for editing.FontEdit()
            regpoly Generate regular polygon. Where is x;y and radius is either r or rx;ry. Rotation is in degrees.regpoly([where,] corners, radius [,rotation])
            Debug Debug action.Debug(...)
            dumpconf Perform 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
            h Print a help message for commands.h
            ApplyVendor Applies the currently loaded vendor drill table to the current design.ApplyVendor()
            LayerBinding Change the layer binding.LayerBinding(object)
            LayerBinding(selected)
            LayerBinding(buffer)
            Puller Pull an arc-line junction tight.pcb_act_Puller()
            m Loads a layout into the current buffer.m [name]
            l Loads layout data.l [name] [format]
            Delete Delete stuff.Delete(Object|Selected)
            Delete(AllRats|SelectedRats)
            q Quits the application after confirming.q
            SetValue Change various board-wide values and sizes.SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)
            s Saves layout data.s [name]
            Message Writes a message to the log window.message(message)
            Mode Change 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)
            ChangeNonetlist Changes the nonetlist flag of elements.ChangeNonetlist(ToggleObject)
            ChangeNonetlist(SelectedElements)
            ChangeNonetlist(Selected|SelectedObjects)
            w Saves layout data.w [name]
            MoveObject Moves the object under the crosshair.pcb_move_obj(X,Y,dim)
            DisperseElements Disperses elements.DisperseElements(All|Selected)
            Atomic Save or restore the undo serial number.Atomic(Save|Restore|Close|Block)
            Info
            PadstackPlace Place a pad stack (either proto_id, or if not specified, the default for style)PadstackPlace([proto_id|default], [x, y])
            dumplayers Print info about each layerdumplayers()
            Backup Backup the current layout - save using the same method that the timed backup function usesBackup()
            dumpfonts Print info about fontsdumpfonts()
            circle Generate a filled circle (zero length round cap line)circle([where,] diameter)
            d1 debug action for developmentd1()
            FullScreen Hide widgets to get edit area full screenpcb_act_FullScreen(on|off|toggle)
            ChkGridSize Return 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)
            LoadTinycadFrom Loads the specified tinycad .net file - the netlist must be tinycad netlist output.LoadTinycadFrom(filename)
            ExecCommand Runs a command.ExecCommand(command)
            PrintPaths Print full paths and search paths.PrintPaths()
            ChkElementName Return 1 if currently shown element label (name) type matches the expectedChkElementName(1) - expect description
            ChkElementName(2) - expect refdes
            ChkElementName(3) - expect value
            ReportObject Report on the object under the crosshairReportObject()
            SaveTo Saves data to a file.SaveTo(Layout|LayoutAs,filename)
            SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)
            SaveTo(PasteBuffer,filename)
            ChangeJoin Changes the join (clearance through polygons) of objects.ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)
            PCBChanged Tells 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])
            Normalize Move all objects within the drawing area, align the drawing to 0;0Normalize()
            ChangeClearSize Changes 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)
            UnloadVendor Unloads the current vendor drill mapping table.UnloadVendor()
            LoadVendorFrom Loads the specified vendor lihata file.LoadVendorFrom(filename)
            LoadMentorFrom Loads the specified Mentor Graphics Design Capture schematics flat .edf file.LoadMentorFrom(filename)
            propset Change the named property of all selected objects to/by valuepropset(name, value)
            q! Quits the application without confirming.q!
            Unselect Unselects the object at the pointer location or the specified objects.Unselect(All|Block|Connection)
            Unselect(ElementByName|ObjectByName|PadByName|PinByName)
            Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)
            Unselect(TextByName|ViaByName)
            Unselect(TextByName|ViaByName, Name)
            Return Simulate a passing or failing action.Return(0|1)
            ChangeSize Changes 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)
            PrintActions Print all actions available.PrintActions()
            NetlistChanged Tells the GUI that the netlist has changed.NetlistChanged()
            jostle Move lines out of the wayJostle(diameter)
            ChangeOctagon Changes the octagon-flag of pins and vias.ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)
            ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)
            ToggleVendor Toggles the state of automatic drill size mapping.ToggleVendor()
            RemoveMenu Recursively removes a new menu, popup (only path specified) or submenu. RemoveMenu(path|cookie)
            FlagEdit Change the layer binding.FlagEdit(object)
            Flip Flip an element to the opposite side of the board.Flip(Object|Selected|SelectedElements)
            ChangeSizes Changes 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)
            ManagePlugins Manage plugins dialog.ManagePlugins()
            align Align ElementsAlign(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])
            dumpundo Print info about fontsdumpfonts()
            PolyOffs replicate 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)
            le Loads an element into the current buffer.le [name]
            MorphPolygon Converts dead polygon islands into separate polygons.pcb_poly_morph(Object|Selected)
            ToPoly convert a closed loop of lines and arcs into a polygonToPoly()
            ToPoly(outline)
            AddRats Add one or more rat lines to the board.AddRats(AllRats|SelectedRats|Close)
            roundrect Generate a rectangle with round cornersroundrect([where,] width[;height] [,rx[;ry] [,rotation]])
            LoadEeschemaFrom Loads the specified eeschema .net file - the netlist must be an s-expression.LoadEeschemaFrom(filename)
            ElementList Adds the given element if it doesn't already exist.ElementList(Start|Done|Need,,,)
            AutoPlaceSelected Auto-place selected components.AutoPlaceSelected()
            DRC Invoke the DRC check.DRC()
            PolyHatch hatch the selected polygon(s) with lines of the current style; lines are drawn on the current layerPolyHatch([spacing], [combination of h|v|c])
            PolyHatch(interactive)
            rn Reads netlist.rn [name]
            FontSave Convert the current PCB back to a font.FontSave()
            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.Editgroup([@group], [name=text|type=+bit|type=-bit])]
            Editlayer([@layer], attrib, key=value)
            ExportScadPoly exports all selected polygons to an openscad script; only the outmost contour of each poly is exportedScadExportPoly(filename)
            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.fp_rehash()
            EnableVendor Enables automatic drill size mapping.EnableVendor()
            Quit Quits the application after confirming.Quit()
            LoadDsnFrom Loads the specified routed dsn file.LoadDsnFrom(filename)
            ClearOctagon Clears the octagon-flag of pins and vias.ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)
            ClearOctagon(SelectedElements|SelectedPins|SelectedVias)
            RemoveSelected Removes any selected objects.pcb_remove_selected()
            MinClearGap Ensures that polygons are a minimum distance from objects.MinClearGap(delta)
            MinClearGap(Selected, delta)
            SetSame Sets current layer and sizes to match indicated item.SetSame()
            wq Saves the layout data and quits.wq
            ChangePaste Changes the no paste flag of objects.ChangePaste(ToggleObject|Object|SelectedPads|Selected)
            Help
            PolyCombine
            DisableVendor Disables automatic drill size mapping.DisableVendor()
            PolyStitch
            Select Toggles or sets the selection.Select(Object|ToggleObject)
            Select(All|Block|Connection)
            Select(ElementByName|ObjectByName|PadByName|PinByName)
            Select(ElementByName|ObjectByName|PadByName|PinByName, Name)
            Select(TextByName|ViaByName|NetByName)
            Select(TextByName|ViaByName|NetByName, Name)
            Select(Convert)
            MinMaskGap Ensures the mask is a minimum distance from pins and pads.MinMaskGap(delta)
            MinMaskGap(Selected, delta)
            ChangeName Sets the name (or pin number) of objects.ChangeName(Object)
            ChangeName(Object|"Number")
            ChangeName(Layout|Layer)
            LoadMucsFrom Loads the specified mucs routing file.LoadMucsFrom(filename)
            DumpPluginDirs Print plugins directories in a format digestable by scripts.DumpPluginDirs()
            GetStyle Return integer index (>=0) of the currently active style or -1 if no style is selected (== custom style)GetStyle()
            ChangeRadius Changes 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)
            + + Index: tags/1.2.7/doc/user/09_appendix/bridges.svg =================================================================== --- tags/1.2.7/doc/user/09_appendix/bridges.svg (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/bridges.svg (revision 13657) @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + 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 + + ipcd356e-tester + + gerber + + (any)EDIF + + TinyCAD + + HPGL(2D CAD) + + LTSpice + + lpr(print) + + breadboard + + mucs PCBautorouter + + XYtemplated + + leptonEDA + + kicadeeschema + + BOM + + openscad(3D CAD) + + (any)netlist + + Mentorhyperlynx + + gEDAgschem + + Eagle(board) + + FidoCadJ(board) + + ProtelAutotrax + + svg + + pngjpg, bmp + + pspostscript + + dxf(2D CAD) + + nelma(sim) + + statstatistics + + + postscript + + + + + svg + + + importschematics + + importnetlist + + + importschematics + + importschematics + + importlines/arcs + + importschematics + + + schematics + + + + boards-expr + + + importnetlist + + + board + + + + .xy + + + + board + + + + boardlegacy + + + + .png + + + + footprint + + + + .grb, .cnc + + + + board + + + + text + + + + footprints-expr + + + + ps + + + importschematics + + + + board + + + + TCP/IP + + + + board + + + + + + IPC356D + + + + board + + + + + + + lihata + + + Index: tags/1.2.7/doc/user/09_appendix/combined_glossary.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/combined_glossary.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/combined_glossary.html (revision 13657) @@ -0,0 +1,281 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd - User Manual: Appendix

            + +

            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/1.2.7/doc/user/09_appendix/dialogtable.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/dialogtable.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/dialogtable.html (revision 13657) @@ -0,0 +1,95 @@ + + + + pcb-rnd + + + + +

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            +pcb-rnd gtk2-gl dialog list, pcb-rnd 1.2.3 + +
            name open hk* exit hk* action focus modality
            main window ctrl-q na na na
            library i esc nk top modeless
            message log various alt-c message normal modeless
            DRC check nk alt-c drc normal modeless
            netlist nk alt-c netlist normal modeless
            command entry : esc nk locks modeless
            pinout shift-d alt-c display(pinout) normal modeless
            font selector ctl-sh-f esc fontsel top modeless
            preferences nk alt-o nk normal modeless
            contextmenu sh-rghtclk esc nk na na
            route styles nk esc route_styles locks modal
            lock dialog f12-sel esc lock top modeless
            + +* hk (hotkeys) assume stock default config
            + Index: tags/1.2.7/doc/user/09_appendix/external_resources.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/external_resources.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/external_resources.html (revision 13657) @@ -0,0 +1,44 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd - user manual appendix

            + +

            9.3.1 pcb-rnd community Resources

            +
              +
            1. repo.hu is the pcb-rnd +maintainer's SVN based project hosting site
            2. +
            3. Contributer erichVK5's blog, +(including many posts directly and indirectly relevant to pcb-rnd)
            4. +
            5. Contributer erichVK5's github
            6. repository +
            + +

            9.3.2 resources on building and contributing to pcb-rnd

            +
              +
            1. contribution guidelines for pcb-rnd
            2. +
            3. live chat with the pcb-rnd user community
            4. +
            5. StackOverflow discussion on using svn
            6. +
            + +

            9.3.3 Printed Circuit Board fabrication Resources

            +
              +
            1. PCB Reference for pth and smt pcb footprint definitions pdf +warning!
            2. +
            3. AN4005 example industry appnote of layout considerations (many abound)
            4. +
            + +

            9.3.4 EDA Resource Links

            +
              +
            1. gEDA
            2. http://www.geda-project.org +
            3. KiCAD
            4. +http://kicad-pcb.org +
            5. Eagle
            6. +https://www.autodesk.com/products/eagle/overview +
            + + Index: tags/1.2.7/doc/user/09_appendix/formats.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/formats.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/formats.html (revision 13657) @@ -0,0 +1,316 @@ + + + + + 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 subcircuit (any version) +
            + lihata pcb-rnd font (any version) +
            + lihata pcb-rnd board (any version) +
            + lihata pcb-rnd subcircuit (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_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 20170123 (s-expr) +
            + eeschema netlist and footprint info +
            + kicad board, version 3 (s-expr) +
            + kicad element (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_dsn +no +works + + import wires and vias from specctra .dsn + +n/a +
            import_edif +no +works + + flat netlist from EDIF + +n/a +
            import_hpgl +no +works + + import lines, arcs and polygons from HPGL plot files + +n/a +
            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 +
            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 elements (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 +Work-in-progress + +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_nelma +no +works + +n/a + + export a board in the nelma format for Numerical capacitance calculation +
            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_xy +no +works + +n/a + + geda/PCB x;y +
            + gxyrs +
            + Macrofab's pick&place +
            + pick&place file for the TM220/TM240 device +
            + KiCad .pos file + +
            + + + Index: tags/1.2.7/doc/user/09_appendix/index.html =================================================================== --- tags/1.2.7/doc/user/09_appendix/index.html (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/index.html (revision 13657) @@ -0,0 +1,21 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd - User Manual: Appendix

            +

            +

            9.0 pcb-rnd action reference

            +
          • pcb-rnd action reference +

            9.1 Glossary of terminology

            +
          • useful terminology for a common +vernacular +

            9.2 External resources

            +
          • useful resources for designing with +pcb-rnd + + + Index: tags/1.2.7/doc/user/09_appendix/src/Makefile =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/Makefile (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/Makefile (revision 13657) @@ -0,0 +1,20 @@ +# NOTE: aagraph is at svn://repo.hu/projects/aagraph/trunk + +CLEANFILES=../action_reference.html ../dialogtable.html ../bridges.svg ../formats.html + +all: ../action_reference.html ../dialogtable.html ../formats.html + +../action_reference.html : ./dump_actions_to_html.sh ../../../../src/pcb-rnd + ./dump_actions_to_html.sh > ../action_reference.html + +../dialogtable.html: pcb-rnd-dialogs ./process_dialogtable.sh ../../../../src/pcb-rnd + ./process_dialogtable.sh > ../dialogtable.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 + +clean: + rm $(CLEANFILES) Index: tags/1.2.7/doc/user/09_appendix/src/bridges.txt =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/bridges.txt (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/bridges.txt (revision 13657) @@ -0,0 +1,281 @@ + *io--------------------------------------------------------------+ + | [kica ] [gpcb ] [hyp_] [gsch] | + | [ frt_ ] [fido] [prtl] [eagl] | + +----------------------------------------------------------------+ +*inp---+ *hid--------+ +|[eesc]| *pcbrnd----------------------------------------------------------+ |[batch ] | +|[mucs]| | | | | +|[lept]| | | |[gtk ] | +|[ltsp]| | | | | +|[tcad]| | | |[lesstif] | +|[edif]| | | | | +|[netl]| | | |[remote] | +|[hpgl]| +----------------------------------------------------------------+ +-----------+ ++------+ + *out-----------------------------------------------------------------+ + | [bbrd] [bom_] [xy__] [gerb] [ipcd] [lpr_] [scad] | [web ] + | [stat] [ps__] [svg_] [png_] [nelm] [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 + +[hpgl] + label HPGL\n(2D CAD) + +[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) + + + +[bbrd] + label breadboard + +[bom_] + label BOM + +[xy__] + label XY\ntemplated + +[gerb] + label gerber + +[ipcd] + 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 + +[nelm] + label nelma\n(sim) + + + + + +[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 ipcd.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 + +-> pcbrnd nelm.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 + +-> 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 + + +<-> pcbrnd batch.w + +<-> pcbrnd gtk.w + +<-> pcbrnd lesstif.w + +<-> pcbrnd remote.w + +<-> remote.s web + label TCP/IP Index: tags/1.2.7/doc/user/09_appendix/src/dump_actions_to_html.sh =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/dump_actions_to_html.sh (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/dump_actions_to_html.sh (revision 13657) @@ -0,0 +1,90 @@ +#!/bin/sh + +# dumps pcb-rnd actions into a simple html table for the docs +# +#errata: pcb_dump_actions function in src/hid_actions.c +# printf("A%s\n", ca->action->name); +# dump_string('D', desc); +# dump_string('S', synt); + + +( + cd ../../../../src + ./pcb-rnd --version + svn info ^/ | awk '/Revision:/ { + print $0 + got_rev=1 + exit + } + END { + if (!got_rev) + print "Rev unknown" + } + ' + ./pcb-rnd --dump-actions +) | awk ' + +function flush_sd() +{ + if (s != "" || d != "" ) { + sub("^
            ", "", d) + sub("^
            ", "", s) + print "
          • " d "" s "
            " + print "\n", $0 + next +} + +/^D/ { + sub("^D", "", $0) + d = d "
            " $0 + next +} + +/^S/ { + sub("^S", "", $0) + s = s "
            " $0 + next +} + +END { + flush_sd() + print "
            " + print pcb_rnd_ver ", " pcb_rnd_rev + print "" + print "
            Action Description Syntax" +} + +/^A/ { + flush_sd() + sub("^A", "", $0) + printf "
            %s
            " + print "" + print "" + +} + +' + + Property changes on: tags/1.2.7/doc/user/09_appendix/src/dump_actions_to_html.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/user/09_appendix/src/gen_formats.sh =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/gen_formats.sh (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/gen_formats.sh (revision 13657) @@ -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/1.2.7/doc/user/09_appendix/src/gen_formats.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/user/09_appendix/src/pcb-rnd-dialogs =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/pcb-rnd-dialogs (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/pcb-rnd-dialogs (revision 13657) @@ -0,0 +1,16 @@ +pcb-rnd gtk2-gl dialog list +name, open hk*, exit hk*, action, focus, modality +main window, , ctrl-q, na, na, na +library, i, esc, nk, top, modeless +message log, various, alt-c, message, normal, modeless +DRC check, nk, alt-c, drc, normal, modeless +netlist, nk, alt-c, netlist, normal, modeless +command entry, :, esc, nk, locks, modeless +pinout, shift-d, alt-c, display(pinout),normal, modeless +font selector, ctl-sh-f, esc, fontsel, top, modeless +preferences, nk, alt-o, nk, normal, modeless +contextmenu, sh-rghtclk, esc, nk, na, na +route styles, nk, esc, route_styles, locks, modal +lock dialog, f12-sel, esc, lock, top, modeless + +* hk (hotkeys) assume stock default config Index: tags/1.2.7/doc/user/09_appendix/src/process_dialogtable.sh =================================================================== --- tags/1.2.7/doc/user/09_appendix/src/process_dialogtable.sh (nonexistent) +++ tags/1.2.7/doc/user/09_appendix/src/process_dialogtable.sh (revision 13657) @@ -0,0 +1,52 @@ +#!/bin/sh +# dumps a csv table of dialog behaviors into a simple html table +awk ' +BEGIN { + pcb_rnd_rev="pcb-rnd 1.2.3" + FS = "," + q="\"" + print "" + print "" + print "" + print " pcb-rnd " + print "" + print "" + print "" + print "" + print "

            " + print "" + print "" + } + +} + +!NF { + exit +} + +// { + printf "\n", $1 + printf "\n", $2 + printf "\n", $3 + printf "\n", $4 + printf "\n", $5 + printf "\n", $6 +} + + +END { + print "
            " + getline + print $0 ", " pcb_rnd_rev + print "" + getline + i = 0 + while (i < NF ) { + i++ + print "
            " $i "
            %s %s %s %s %s %s
            " + print "" + getline + print $0 "
            " + print "" +} +' pcb-rnd-dialogs Property changes on: tags/1.2.7/doc/user/09_appendix/src/process_dialogtable.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc/user/Makefile =================================================================== --- tags/1.2.7/doc/user/Makefile (nonexistent) +++ tags/1.2.7/doc/user/Makefile (revision 13657) @@ -0,0 +1,18 @@ +TRUNK=../.. +BUILD=$(TRUNK)/util/build_ps.sh + +export HTML2PS_OPTS=-f default.css +export HTML2PS_SED="s^<[hH]1>.*^^g" + +all: user.pdf + +user.ps: ps.lst $(BUILD) default.css Makefile + $(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 Index: tags/1.2.7/doc/user/default.css =================================================================== --- tags/1.2.7/doc/user/default.css (nonexistent) +++ tags/1.2.7/doc/user/default.css (revision 13657) @@ -0,0 +1,40 @@ +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; +} + +table { + border-collapse: collapse; + border: 2px solid #555555; +} + +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/1.2.7/doc/user/index.html =================================================================== --- tags/1.2.7/doc/user/index.html (nonexistent) +++ tags/1.2.7/doc/user/index.html (revision 13657) @@ -0,0 +1,24 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd - user manual

            + +

            Table of Contents

            +

            +

            + Index: tags/1.2.7/doc/user/title.html =================================================================== --- tags/1.2.7/doc/user/title.html (nonexistent) +++ tags/1.2.7/doc/user/title.html (revision 13657) @@ -0,0 +1,19 @@ + + +

            +

            +

            +

            +

            +

            +

            +

            +

            +

            PCB-rnd

            +

            +

            +

            User manual

            +

            +

            + + Index: tags/1.2.7/doc/windows.txt =================================================================== --- tags/1.2.7/doc/windows.txt (nonexistent) +++ tags/1.2.7/doc/windows.txt (revision 13657) @@ -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, nelma) + +Worked on systems: + - Windows 8.1 pro, Hungarian, 32 bit + - Windows 7 pro, Hungarian, 64 bit + - Windows 7 pro, English, 64 bit Index: tags/1.2.7/doc/wishlist.txt =================================================================== --- tags/1.2.7/doc/wishlist.txt (nonexistent) +++ tags/1.2.7/doc/wishlist.txt (revision 13657) @@ -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] + W2: proper primitives - data model rewrite [Chris] + +User wishes fulfilled: + 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/1.2.7/doc-orig/Makefile =================================================================== --- tags/1.2.7/doc-orig/Makefile (nonexistent) +++ tags/1.2.7/doc-orig/Makefile (revision 13657) @@ -0,0 +1,154 @@ +## -*- makefile -*- +## +## COPYRIGHT +## +## 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., 675 Mass Ave, Cambridge, MA 02139, USA. +## +## Contact addresses for paper mail and Email: +## Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany +## Thomas.Nau@rz.uni-ulm.de +## + +## not until it is fully fixed up in terms of building +##SUBDIRS= gs + +info_TEXINFOS= pcb.texi +pcb_TEXINFOS= ${inline_texi} ${pcb_output} ${tab_texi} ${images_output} + +dist_html_DATA= ${html_docs} ${pcb_output_inst} ${images_output_inst} + +dist_man_MANS= pcb.1 + +html_docs= ${info_TEXINFOS:.texi=.html} + +DVIS= + +# put the html manual into 1 file instead of multiple files? +AM_MAKEINFOHTMLFLAGS= --css-include=pcb.css --no-split + +EXTRA_DIST= \ + ascii2texi.awk \ + eps2png \ + extract-docs \ + refcard.tex \ + pcb.css \ + ${inline_texi} \ + ${pcb_files} \ + ${pcb_output_noinst} \ + ${tab_files} \ + ${tab_texi} \ + ${images} + +all: + @echo "***" + @echo "*** Compiling the old docs is disabled. We keep last compilation as static doc to edit until it is replaced with the new docs. ***" + @echo "***" + @false + +old_all: $(html_docs) + +# use this to avoid having the clean target delete pcb.{dvi,html,pdf,ps} +# which unfortunately deletes files which are part of the distfile +clean: + -rm -rf pcb.aux pcb.cp pcb.cps pcb.fn pcb.fns pcb.ky pcb.kys pcb.log pcb.pg \ + pcb.pgs pcb.tmp pcb.toc pcb.tp pcb.tps pcb.vr pcb.vrs + + +BUILT_SOURCES= ${tab_texi} ${pcb_output} ${inline_texi} +CLEANFILES= \ + refcard.aux refcard.log refcard.pdf \ + ${pcb_output} ${tab_texi} ${inline_texi} pcb.html \ + ${images_output} + +inline_texi= \ + options.texi \ + actions.texi \ + pcbfile.texi + +ASCII2TEXI= ${AWK} -f $(srcdir)/ascii2texi.awk ncol=3 + +# Tables +tab_files= \ + fractional_size.tab \ + letter_size.tab \ + metric_size.tab \ + wire_size.tab +tab_texi= ${tab_files:.tab=.texi} + +# PCB Drawings +pcb_files= \ + pad.pcb \ + puller.pcb \ + thermal.pcb \ + gcode.pcb + +pcb_output_noinst= \ + ${pcb_files:.pcb=.pdf} + +pcb_output_inst= \ + ${pcb_files:.pcb=.png} + +pcb_output= ${pcb_output_inst} ${pcb_output_noinst} + +# Additional images +images= \ + gcode_control_img.eps \ + gcode_tool_path.eps + +images_output_noinst= \ + ${images:.eps=.pdf} + +images_output_inst= \ + ${images:.eps=.png} + +images_output= ${images_output_noinst} ${images_output_inst} + +${inline_texi} : extracted-docs + +# no need to build these when building via a tarball. They're not used then +# anyway. +.PHONY : extracted-docs +extracted-docs : + ${PERL} $(srcdir)/extract-docs $(srcdir) + +SUFFIXES = .eps .pcb .pdf .png .tab .tex .html .texi + +.pcb.eps : + ${PCB} -x eps --only-visible --font-path $(top_srcdir)/src --eps-file $@ $< + +.pcb.png : + ${PCB} -x png --only-visible --font-path $(top_srcdir)/src --outfile $@ $< + +.eps.pdf : + ${PS2PDF} `${AWK} 'BEGIN{s=8}; /BoundingBox/ {printf("-r%d -g%dx%d", s*72, s*$$4, s*$$5);}' $<` $< $@ + +.tab.texi: + ${ASCII2TEXI} $< > $@ + +.tex.pdf: + ${PDFLATEX} $< + ${PDFLATEX} $< + ${PDFLATEX} $< + +.eps.png: + ${PERL} $(srcdir)/eps2png --png $< > $@ + +%.html: %.texi + rm $@ 2>/dev/null; true + makeinfo --html --css-include=pcb.css --no-split --output=$@ $^ + Index: tags/1.2.7/doc-orig/README =================================================================== --- tags/1.2.7/doc-orig/README (nonexistent) +++ tags/1.2.7/doc-orig/README (revision 13657) @@ -0,0 +1,10 @@ +This is the original doc dir of pcb. + +For the modifications introduced by pcb-rnd, check ../doc-rnd + +Most of the original documentation is in texi; makeinfo fails to +produce pdf from pcb.texi and even generating html throws +a large amount of warnings. + +It may be that pcb-rnd will switch from texi to html for documentation +source format. Index: tags/1.2.7/doc-orig/README.w32 =================================================================== --- tags/1.2.7/doc-orig/README.w32 (nonexistent) +++ tags/1.2.7/doc-orig/README.w32 (revision 13657) @@ -0,0 +1,24 @@ +(not updated for pcb-rnd yet) + +Building PCB for Windows with a MinGW cross-compiler + +1) Install a MinGW cross-compiler. +On Debian and derivatives, you can type 'sudo apt-get install mingw32.'. +You can also build your own by using the build script provided by the +MinGW project. + +2) Install native (non-cross) dependencies. + +* autoconf, automake, libtool, gettext, intltool. +* glib and gtk+. + +3) Edit the w32/minipack.conf file to suit your compiler setup. + +4) Enter the w32 directory and run ./build_all. + +5) Wait while the script fetches and compiles the PCB dependencies and PCB itself. + +6) Run the result with wine: wine result/bin/pcb.exe + +7) Copy the result directory to a Windows installation (packaging script is not supplied). + Index: tags/1.2.7/doc-orig/actions.texi =================================================================== --- tags/1.2.7/doc-orig/actions.texi (nonexistent) +++ tags/1.2.7/doc-orig/actions.texi (revision 13657) @@ -0,0 +1,3574 @@ +@c key actions +@c ./../src/action.c 225 + +Many actions take a @code{delta} parameter as the last parameter, +which is an amount to change something. That @code{delta} may include +units, as an additional parameter, such as @code{Action(Object,5,mm)}. +If no units are specified, the default is PCB's native units +(currently 1/100 mil). Also, if the delta is prefixed by @code{+} or +@code{-}, the size is increased or decreased by that amount. +Otherwise, the size size is set to the given amount. + +@example +Action(Object,5,mil) +Action(Object,+0.5,mm) +Action(Object,-1) +@end example + +Actions which take a @code{delta} parameter which do not accept all +these options will specify what they do take. + +@c ./../src/action.c 229 + +@macro pinshapes + +Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +@end macro + +@c ./../src/command.c 64 + +@macro colonaction + +This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (@code{:}) and thus the syntax +is documented for that purpose. + +@end macro + +@c ./../src/action.c 227 + +Many actions act on indicated objects on the board. They will have +parameters like @code{ToggleObject} or @code{SelectedVias} to indicate +what group of objects they act on. Unless otherwise specified, these +parameters are defined as follows: + +@table @code + +@item Object +@itemx ToggleObject +Affects the object under the mouse pointer. If this action is invoked +from a menu or script, the user will be prompted to click on an +object, which is then the object affected. + +@item Selected +@itemx SelectedObjects + +Affects all objects which are currently selected. At least, all +selected objects for which the given action makes sense. + +@item SelectedPins +@itemx SelectedVias +@itemx Selected@var{Type} +@itemx @i{etc} +Affects all objects which are both selected and of the @var{Type} specified. + +@end table + + +@menu +* core actions:: +* common actions:: +* gtk actions:: +* lesstif actions:: +@end menu + +@node core actions +@section Core actions +@menu +* AddRats Action:: Add one or more rat lines to the board. +* ApplyVendor Action:: Applies the currently loaded vendor drill table to the current design. +* Atomic Action:: Save or restore the undo serial number. +* Attributes Action:: Let the user edit the attributes of the layout, current or given +layer, or selected element. +* AutoPlaceSelected Action:: Auto-place selected components. +* AutoRoute Action:: Auto-route some or all rat lines. +* ChangeClearSize Action:: Changes the clearance size of objects. +* ChangeDrillSize Action:: Changes the drilling hole size of objects. +* ChangeFlag Action:: Sets or clears flags on objects. +* ChangeHole Action:: Changes the hole flag of objects. +* ChangeJoin Action:: Changes the join (clearance through polygons) of objects. +* ChangeName Action:: Sets the name of objects. +* ChangeOctagon Action:: Changes the octagon-flag of pins and vias. +* ChangePaste Action:: Changes the no paste flag of objects. +* ChangePinName Action:: Sets the name of a specific pin on a specific element. +* ChangeSize Action:: Changes the size of objects. +* ChangeSquare Action:: Changes the square flag of pins and pads. +* ClearOctagon Action:: Clears the octagon-flag of pins and vias. +* ClearSquare Action:: Clears the square-flag of pins and pads. +* ClrFlag Action:: Clears flags on objects. +* Connection Action:: Searches connections of the object at the cursor position. +* Delete Action:: Delete stuff. +* DeleteRats Action:: Delete rat lines. +* DisableVendor Action:: Disables automatic drill size mapping. +* DisperseElements Action:: Disperses elements. +* Display Action:: Several display-related actions. +* djopt Action:: Perform various optimizations on the current board. +* DRC Action:: Invoke the DRC check. +* DumpLibrary Action:: Display the entire contents of the libraries. +* elementlist Action:: Adds the given element if it doesn't already exist. +* elementsetattr Action:: Sets or clears an element-specific attribute. +* EnableVendor Action:: Enables automatic drill size mapping. +* execcommand Action:: Runs a command. +* ExecuteFile Action:: Run actions from the given file. +* Flip Action:: Flip an element to the opposite side of the board. +* FontEdit Action:: Convert the current font to a PCB for editing. +* FontSave Action:: Convert the current PCB back to a font. +* FreeRotateBuffer Action:: 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. + +* GlobalPuller Action:: Pull all traces tight. +* h Action:: Print a help message for commands. +* Import Action:: Import schematics. +* l Action:: Loads layout data. +* le Action:: Loads an element into the current buffer. +* LoadFootprint Action:: Loads a single footprint by name. +* LoadFrom Action:: Load layout data from a file. +* LoadVendorFrom Action:: Loads the specified vendor resource file. +* m Action:: Loads a layout into the current buffer. +* MarkCrosshair Action:: Set/Reset the Crosshair mark. +* Message Action:: Writes a message to the log window. +* MinClearGap Action:: Ensures that polygons are a minimum distance from objects. +* MinMaskGap Action:: Ensures the mask is a minimum distance from pins and pads. +* Mode Action:: Change or use the tool mode. +* MorphPolygon Action:: Converts dead polygon islands into separate polygons. +* MoveLayer Action:: Moves/Creates/Deletes Layers. +* MoveObject Action:: Moves the object under the crosshair. +* MoveToCurrentLayer Action:: Moves objects to the current layer. +* Netlist Action:: Perform various actions on netlists. +* New Action:: Starts a new layout. +* OptAutoOnly Action:: Toggles the optimize-only-autorouted flag. +* PasteBuffer Action:: Various operations on the paste buffer. +* Polygon Action:: Some polygon related stuff. +* Puller Action:: Pull an arc-line junction tight. +* q Action:: Quits the application after confirming. +* q! Action:: Quits the application without confirming. +* Quit Action:: Quits the application after confirming. +* Redo Action:: Redo recent``undo''operations. +* RemoveSelected Action:: Removes any selected objects. +* Renumber Action:: Renumber all elements. The changes will be recorded to filename +for use in backannotating these changes to the schematic. +* Report Action:: Produce various report. +* ReportDialog Action:: Report on the object under the crosshair +* RipUp Action:: Ripup auto-routed tracks, or convert an element to parts. +* rn Action:: Reads netlist. +* RouteStyle Action:: Copies the indicated routing style into the current sizes. +* s Action:: Saves layout data. +* SaveSettings Action:: Saves settings. +* SaveTo Action:: Saves data to a file. +* Select Action:: Toggles or sets the selection. +* SetFlag Action:: Sets flags on objects. +* SetOctagon Action:: Sets the octagon-flag of objects. +* SetSame Action:: Sets current layer and sizes to match indicated item. +* SetSquare Action:: sets the square-flag of objects. +* SetThermal Action:: Set the thermal (on the current layer) of pins or vias 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. + +* SetValue Action:: Change various board-wide values and sizes. +* ToggleHideName Action:: Toggles the visibility of element names. +* ToggleVendor Action:: Toggles the state of automatic drill size mapping. +* Undo Action:: Undo recent changes. +* UnloadVendor Action:: Unloads the current vendor drill mapping table. +* Unselect Action:: Unselects the object at the pointer location or the specified objects. +* w Action:: Saves layout data. +* wq Action:: Saves the layout data and quits. +@end menu +@node AddRats Action +@subsection AddRats +@c key AddRats in hid +@cartouche +@format +AddRats(AllRats|SelectedRats|Close)@end format +@end cartouche + +Add one or more rat lines to the board. +@c ./../src/action.c 3310 + +@table @code + +@item AllRats +Create rat lines for all loaded nets that aren't already connected on +with copper. + +@item 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. + +@end table + + +@node ApplyVendor Action +@subsection ApplyVendor +@c key ApplyVendor in hid +@cartouche +@format +ApplyVendor()@end format +@end cartouche + +Applies the currently loaded vendor drill table to the current design. +@c ./../src/vendor.c 112 +@cindex vendor map +@cindex vendor drill table +@findex ApplyVendor() + +This will modify all of your drill holes to match the list of allowed +sizes for your vendor. + +@node Atomic Action +@subsection Atomic +@c key Atomic in hid +@cartouche +@format +Atomic(Save|Restore|Close|Block)@end format +@end cartouche + +Save or restore the undo serial number. +@c ./../src/action.c 1720 + +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 @code{Save}, +delete the rats, @code{Restore}, add the rats - using the same serial +number as the deletes, then @code{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. + +@table @code + +@item Save +Saves the undo serial number. + +@item Restore +Returns it to the last saved number. + +@item Close +Sets it to 1 greater than the last save. + +@item Block +Does a Restore if there was nothing to undo, else does a Close. + +@end table + + +@node Attributes Action +@subsection Attributes +@c key Attributes in hid +@cartouche +@format +Attributes(Layout|Layer|Element) +Attributes(Layer,layername)@end format +@end cartouche + +Let the user edit the attributes of the layout, current or given +layer, or selected element. +@c ./../src/action.c 6761 + +This just pops up a dialog letting the user edit the attributes of the +pcb, an element, or a layer. + + +@node AutoPlaceSelected Action +@subsection AutoPlaceSelected +@c key AutoPlaceSelected in hid +@cartouche +@format +AutoPlaceSelected()@end format +@end cartouche + +Auto-place selected components. +@c ./../src/action.c 3450 + +Attempts to re-arrange the selected components such that the nets +connecting them are minimized. Note that you cannot undo this. + + +@node AutoRoute Action +@subsection AutoRoute +@c key AutoRoute in hid +@cartouche +@format +AutoRoute(AllRats|SelectedRats)@end format +@end cartouche + +Auto-route some or all rat lines. +@c ./../src/action.c 3471 + +@table @code + +@item AllRats +Attempt to autoroute all rats. + +@item SelectedRats +Attempt to autoroute the selected rats. + +@end table + +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 line and via +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. + + +@node ChangeClearSize Action +@subsection ChangeClearSize +@c key ChangeClearSize in hid +@cartouche +@format +ChangeClearSize(Object, delta) +ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta) +ChangeClearSize(SelectedLines|SelectedArcs, delta +ChangeClearSize(Selected|SelectedObjects, delta)@end format +@end cartouche + +Changes the clearance size of objects. +@c ./../src/action.c 3686 + +If the solder mask is currently showing, this action changes the +solder mask clearance. If the mask is not showing, this action +changes the polygon clearance. + + +@node ChangeDrillSize Action +@subsection ChangeDrillSize +@c key ChangeDrillSize in hid +@cartouche +@format +ChangeDrillSize(Object, delta) +ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta)@end format +@end cartouche + +Changes the drilling hole size of objects. +@c ./../src/action.c 3630 + + +@node ChangeFlag Action +@subsection ChangeFlag +@c key ChangeFlag in hid +@cartouche +@format +ChangeFlag(Object|Selected|SelectedObjects, flag, value) +ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value) +ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value) +ChangeFlag(SelectedElements, flag, value) +flag = square | octagon | thermal | join +value = 0 | 1@end format +@end cartouche + +Sets or clears flags on objects. +@c ./../src/action.c 5750 + +Toggles the given flag on the indicated object(s). The flag may be +one of the flags listed above (square, octagon, 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. + + +@node ChangeHole Action +@subsection ChangeHole +@c key ChangeHole in hid +@cartouche +@format +ChangeHole(ToggleObject|Object|SelectedVias|Selected)@end format +@end cartouche + +Changes the hole flag of objects. +@c ./../src/action.c 4571 + +The "hole flag" of a via determines whether the via is a +plated-through hole (not set), or an unplated hole (set). + + +@node ChangeJoin Action +@subsection ChangeJoin +@c key ChangeJoin in hid +@cartouche +@format +ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)@end format +@end cartouche + +Changes the join (clearance through polygons) of objects. +@c ./../src/action.c 4199 + +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. + + +@node ChangeName Action +@subsection ChangeName +@c key ChangeName in hid +@cartouche +@format +ChangeName(Object) +ChangeName(Layout|Layer)@end format +@end cartouche + +Sets the name of objects. +@c ./../src/action.c 4005 + +@table @code + +@item Object +Changes the name of the element under the cursor. + +@item Layout +Changes the name of the layout. This is printed on the fab drawings. + +@item Layer +Changes the name of the currently active layer. + +@end table + + +@node ChangeOctagon Action +@subsection ChangeOctagon +@c key ChangeOctagon in hid +@cartouche +@format +ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected) +ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)@end format +@end cartouche + +Changes the octagon-flag of pins and vias. +@c ./../src/action.c 4403 + +@pinshapes + + +@node ChangePaste Action +@subsection ChangePaste +@c key ChangePaste in hid +@cartouche +@format +ChangePaste(ToggleObject|Object|SelectedPads|Selected)@end format +@end cartouche + +Changes the no paste flag of objects. +@c ./../src/action.c 4611 + +The "no paste flag" of a pad determines whether the solderpaste + stencil will have an opening for the pad (no set) or if there wil be + no solderpaste on the pad (set). This is used for things such as + fiducial pads. + + +@node ChangePinName Action +@subsection ChangePinName +@c key ChangePinName in hid +@cartouche +@format +ChangePinName(ElementName,PinNumber,PinName)@end format +@end cartouche + +Sets the name of a specific pin on a specific element. +@c ./../src/action.c 3924 + +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) +@end example + + +@node ChangeSize Action +@subsection ChangeSize +@c key ChangeSize in hid +@cartouche +@format +ChangeSize(Object, delta) +ChangeSize(SelectedObjects|Selected, delta) +ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta) +ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta) +ChangeSize(SelectedElements, delta)@end format +@end cartouche + +Changes the size of objects. +@c ./../src/action.c 3543 + +For lines and arcs, this changes the width. For pins and vias, this +changes the overall diameter of the copper annulus. For pads, this +changes the width and, indirectly, the length. For texts and names, +this changes the scaling factor. For elements, this changes the width +of the silk layer lines and arcs for this element. + + +@node ChangeSquare Action +@subsection ChangeSquare +@c key ChangeSquare in hid +@cartouche +@format +ChangeSquare(ToggleObject) +ChangeSquare(SelectedElements|SelectedPins) +ChangeSquare(Selected|SelectedObjects)@end format +@end cartouche + +Changes the square flag of pins and pads. +@c ./../src/action.c 4250 + +Note that @code{Pins} means both pins and pads. + +@pinshapes + + +@node ClearOctagon Action +@subsection ClearOctagon +@c key ClearOctagon in hid +@cartouche +@format +ClearOctagon(ToggleObject|Object|SelectedObjects|Selected) +ClearOctagon(SelectedElements|SelectedPins|SelectedVias)@end format +@end cartouche + +Clears the octagon-flag of pins and vias. +@c ./../src/action.c 4515 + +@pinshapes + + +@node ClearSquare Action +@subsection ClearSquare +@c key ClearSquare in hid +@cartouche +@format +ClearSquare(ToggleObject|SelectedElements|SelectedPins)@end format +@end cartouche + +Clears the square-flag of pins and pads. +@c ./../src/action.c 4352 + +Note that @code{Pins} means pins and pads. + +@pinshapes + + +@node ClrFlag Action +@subsection ClrFlag +@c key ClrFlag in hid +@cartouche +@format +ClrFlag(Object|Selected|SelectedObjects, flag) +ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag) +ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag) +ClrFlag(SelectedElements, flag) +flag = square | octagon | thermal | join@end format +@end cartouche + +Clears flags on objects. +@c ./../src/action.c 5733 + +Turns the given flag off, regardless of its previous setting. See +@code{ChangeFlag}. + +@example +ClrFlag(SelectedLines,join) +@end example + + +@node Connection Action +@subsection Connection +@c key Connection in hid +@cartouche +@format +Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)@end format +@end cartouche + +Searches connections of the object at the cursor position. +@c ./../src/action.c 2093 + +Connections found with this action will be highlighted in the +``connected-color'' color and will have the ``found'' flag set. + +@table @code + +@item Find +The net under the cursor is ``found''. + +@item ResetLinesAndPolygons +Any ``found'' lines and polygons are marked ``not found''. + +@item ResetPinsAndVias +Any ``found'' pins and vias are marked ``not found''. + +@item Reset +All ``found'' objects are marked ``not found''. + +@end table + + +@node Delete Action +@subsection Delete +@c key Delete in hid +@cartouche +@format +Delete(Object|Selected) +Delete(AllRats|SelectedRats)@end format +@end cartouche + +Delete stuff. +@c ./../src/action.c 3371 + + +@node DeleteRats Action +@subsection DeleteRats +@c key DeleteRats in hid +@cartouche +@format +DeleteRats(AllRats|Selected|SelectedRats)@end format +@end cartouche + +Delete rat lines. +@c ./../src/action.c 3418 + + +@node DisableVendor Action +@subsection DisableVendor +@c key DisableVendor in hid +@cartouche +@format +DisableVendor()@end format +@end cartouche + +Disables automatic drill size mapping. +@c ./../src/vendor.c 161 + +@cindex vendor map +@cindex vendor drill table +@findex DisableVendor() + +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. + + +@node DisperseElements Action +@subsection DisperseElements +@c key DisperseElements in hid +@cartouche +@format +DisperseElements(All|Selected)@end format +@end cartouche + +Disperses elements. +@c ./../src/action.c 2146 + +Normally this is used when starting a board, by selecting all elements +and then dispersing them. This scatters the elements around the board +so that you can pick individual ones, rather than have all the +elements at the same 0,0 coordinate and thus impossible to choose +from. + + +@node Display Action +@subsection Display +@c key Display in hid +@cartouche +@format +Display(NameOnPCB|Description|Value) +Display(Grid|Redraw) +Display(CycleClip|CycleCrosshair|Toggle45Degree|ToggleStartDirection) +Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames) +Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin) +Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef) +Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC) +Display(ToggleLiveRoute|LockNames|OnlyNames) +Display(Pinout|PinOrPadName)@end format +@end cartouche + +Several display-related actions. +@c ./../src/action.c 2262 + +@table @code + +@item NameOnPCB +@item Description +@item Value +Specify whether all elements show their name, description, or value. + +@item Redraw +Redraw the whole board. + +@item Toggle45Degree +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. + +@item 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. + +@item CycleCrosshair +Changes crosshair drawing. Crosshair may accept form of 4-ray, +8-ray and 12-ray cross. + +@item ToggleRubberBandMode +If set, moving an object moves all the lines attached to it too. + +@item ToggleStartDirection +If set, each time you set a point in a line, the Clip toggles between +orth-angle and angle-ortho. + +@item ToggleUniqueNames +If set, you will not be permitted to change the name of an element to +match that of another element. + +@item ToggleSnapPin +If set, pin centers and pad end points are treated as additional grid +points that the cursor can snap to. + +@item ToggleLocalRef +If set, the mark is automatically set to the beginning of any move, so +you can see the relative distance you've moved. + +@item 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. + +@item ToggleThindrawPoly +If set, polygons on the screen are drawn as outlines. + +@item 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. + +@item ToggleLiveRoute +If set, the progress of the autorouter will be visible on the screen. + +@item ToggleAutoDRC +If set, you will not be permitted to make connections which violate +the current DRC and netlist settings. + +@item 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. + +@item ToggleOrthoMove +If set, the crosshair is only allowed to move orthogonally from its +previous position. I.e. you can move an element or line up, down, +left, or right, but not up+left or down+right. + +@item ToggleName +Selects whether the pinouts show the pin names or the pin numbers. + +@item 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. + +@item 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. + +@item ToggleMask +Turns the solder mask on or off. + +@item 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. + +@item 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. + +@item ToggleGrid +Resets the origin of the current grid to be wherever the mouse pointer +is (not where the crosshair currently is). If you provide two numbers +after this, the origin is set to that coordinate. + +@item Grid +Toggles whether the grid is displayed or not. + +@item Pinout +Causes the pinout of the element indicated by the cursor to be +displayed, usually in a separate window. + +@item PinOrPadName +Toggles whether the names of pins, pads, or (yes) vias will be +displayed. If the cursor is over an element, all of its pins and pads +are affected. + +@end table + + +@node djopt Action +@subsection djopt +@c key djopt in hid +@cartouche +@format +djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull) +djopt(auto) - all of the above +djopt(miter)@end format +@end cartouche + +Perform various optimizations on the current board. +@c ./../src/djopt.c 2853 + +The different types of optimizations change your board in order to +reduce the total trace length and via count. + +@table @code + +@item debumpify +Looks for U-shaped traces that can be shortened or eliminated. + +@item unjaggy +Looks for corners which could be flipped to eliminate one or more +corners (i.e. jaggy lines become simpler). + +@item 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. + +@item 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). + +@item viatrim +Looks for traces that go from via to via, where moving that trace to a +different layer eliminates one or both vias. + +@item 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. + +@item splitlines +Looks for lines that pass through vias, pins, or pads, and splits them +into separate lines so they can be managed separately. + +@item auto +Performs the above options, repeating until no further optimizations +can be made. + +@item miter +Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. + +@end table + + +@node DRC Action +@subsection DRC +@c key DRC in hid +@cartouche +@format +DRC()@end format +@end cartouche + +Invoke the DRC check. +@c ./../src/action.c 1755 + +Note that the design rule check uses the current board rule settings, +not the current style settings. + + +@node DumpLibrary Action +@subsection DumpLibrary +@c key DumpLibrary in hid +@cartouche +@format +DumpLibrary()@end format +@end cartouche + +Display the entire contents of the libraries. +@c ./../src/action.c 1791 + + + +@node elementlist Action +@subsection elementlist +@c key elementlist in hid +@cartouche +@format +ElementList(Start|Done|Need,,,)@end format +@end cartouche + +Adds the given element if it doesn't already exist. +@c ./../src/action.c 5983 + +@table @code + +@item Start +Indicates the start of an element list; call this before any Need +actions. + +@item Need +Searches the board for an element with a matching refdes. + +If found, the value and footprint are updated. + +If not found, a new element is created with the given footprint and value. + +@item Done +Compares the list of elements needed since the most recent +@code{start} with the list of elements actually on the board. Any +elements that weren't listed are selected, so that the user may delete +them. + +@end table + + +@node elementsetattr Action +@subsection elementsetattr +@c key elementsetattr in hid +@cartouche +@format +ElementSetAttr(refdes,name[,value])@end format +@end cartouche + +Sets or clears an element-specific attribute. +@c ./../src/action.c 6176 + +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. + + +@node EnableVendor Action +@subsection EnableVendor +@c key EnableVendor in hid +@cartouche +@format +EnableVendor()@end format +@end cartouche + +Enables automatic drill size mapping. +@c ./../src/vendor.c 146 + +@cindex vendor map +@cindex vendor drill table +@findex EnableVendor() + +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. To enable drill +mapping, a vendor resource file containing a drill table must be +loaded first. + + +@node execcommand Action +@subsection execcommand +@c key execcommand in hid +@cartouche +@format +ExecCommand(command)@end format +@end cartouche + +Runs a command. +@c ./../src/action.c 6234 + +Runs the given command, which is a system executable. + + +@node ExecuteFile Action +@subsection ExecuteFile +@c key ExecuteFile in hid +@cartouche +@format +ExecuteFile(filename)@end format +@end cartouche + +Run actions from the given file. +@c ./../src/action.c 5861 + +Lines starting with @code{#} are ignored. + + +@node Flip Action +@subsection Flip +@c key Flip in hid +@cartouche +@format +Flip(Object|Selected|SelectedElements)@end format +@end cartouche + +Flip an element to the opposite side of the board. +@c ./../src/action.c 1841 + +Note that the location of the element 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 element is on the other side. When flipping +multiple elements, this retains their positions relative to each +other, not their absolute positions on the board. + + +@node FontEdit Action +@subsection FontEdit +@c key FontEdit in hid +@cartouche +@format +FontEdit()@end format +@end cartouche + +Convert the current font to a PCB for editing. +@c ./../src/fontmode.c 73 + + +@node FontSave Action +@subsection FontSave +@c key FontSave in hid +@cartouche +@format +FontSave()@end format +@end cartouche + +Convert the current PCB back to a font. +@c ./../src/fontmode.c 173 + + +@node FreeRotateBuffer Action +@subsection FreeRotateBuffer +@c key FreeRotateBuffer in hid +@cartouche +@format +FreeRotateBuffer([Angle])@end format +@end cartouche + +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. + +@c ./../src/buffer.c 1370 + +Rotates the contents of the pastebuffer by an arbitrary angle. If no +angle is given, the user is prompted for one. + + +@node GlobalPuller Action +@subsection GlobalPuller +@c key GlobalPuller in hid +@cartouche +@format +GlobalPuller()@end format +@end cartouche + +Pull all traces tight. +@c ./../src/puller.c 534 + + +@node h Action +@subsection h +@c key h in hid +@cartouche +@format +h@end format +@end cartouche + +Print a help message for commands. +@c ./../src/command.c 72 + +@colonaction + + +@node Import Action +@subsection Import +@c key Import in hid +@cartouche +@format +Import() +Import([gnetlist|make[,source,source,...]]) +Import(setnewpoint[,(mark|center|X,Y)]) +Import(setdisperse,D,units) +@end format +@end cartouche + +Import schematics. +@c ./../src/action.c 6464 + +Imports element and netlist data from the schematics (or some other +source). The first parameter, which is optional, is the mode. If not +specified, the @code{import::mode} attribute in the PCB is used. +@code{gnetlist} means gnetlist is used to obtain the information from +the schematics. @code{make} invokes @code{make}, assuming the user +has a @code{Makefile} in the current directory. The @code{Makefile} +will be invoked with the following variables set: + +@table @code + +@item PCB +The name of the .pcb file + +@item SRCLIST +A space-separated list of source files + +@item 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 @code{import::outfile} +attribute, that file name is used instead (and not automatically +deleted afterwards). + +@end table + +The target specified to be built is the first of these that apply: + +@itemize @bullet + +@item +The target specified by an @code{import::target} attribute. + +@item +The output file specified by an @code{import::outfile} attribute. + +@item +If nothing else is specified, the target is @code{pcb_import}. + +@end itemize + +If you specify an @code{import::makefile} attribute, then "-f " 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 @code{import::src@var{N}} attributes (like +@code{import::src0}, @code{import::src1}, etc). + +For compatibility with future extensions to the import file format, +the generated file @emph{must not} start with the two characters +@code{#%}. + +If a temporary file is needed the @code{TMPDIR} environment variable +is used to select its location. + +Note that the programs @code{gnetlist} and @code{make} may be +overridden by the user via the @code{make-program} and @code{gnetlist} +@code{pcb} settings (i.e. in @code{~/.pcb/settings} or on the command +line). + +If @pcb{} cannot determine which schematic(s) to import from, the GUI +is called to let user choose (see @code{ImportGUI()}). + +Note that Import() doesn't delete anything - after an Import, elements +which shouldn't be on the board are selected and may be removed once +it's determined that the deletion is appropriate. + +If @code{Import()} is called with @code{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. + +@table @code + +@item 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. + +@item Import(setnewpoint,mark) + +Uses the location of the mark. If no mark is present, the point is +not changed. + +@item Import(setnewpoint,center) + +Resets the point to the center of the board. + +@item Import(setnewpoint,X,Y,units) + +Sets the point to the specific coordinates given. Example: +@code{Import(setnewpoint,50,25,mm)} + +@end table + +Note that the X and Y locations are stored in attributes named +@code{import::newX} and @code{import::newY} so you could change them +manually if you wished. + +Calling @code{Import(setdisperse,D,units)} sets how much the newly +placed elements are dispersed relative to the set point. For example, +@code{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 +@code{import::disperse} attribute. + + +@node l Action +@subsection l +@c key l in hid +@cartouche +@format +l [name]@end format +@end cartouche + +Loads layout data. +@c ./../src/command.c 99 + +Loads a new datafile (layout) and, if confirmed, overwrites any +existing unsaved data. The filename and the searchpath +(@emph{filePath}) are passed to the command defined by +@emph{fileCommand}. If no filename is specified a file select box +will popup. + +@colonaction + + +@node le Action +@subsection le +@c key le in hid +@cartouche +@format +le [name]@end format +@end cartouche + +Loads an element into the current buffer. +@c ./../src/command.c 129 + +The filename and the searchpath (@emph{elementPath}) are passed to the +command defined by @emph{elementCommand}. If no filename is specified +a file select box will popup. + +@colonaction + + +@node LoadFootprint Action +@subsection LoadFootprint +@c key LoadFootprint in hid +@cartouche +@format +LoadFootprint(filename[,refdes,value])@end format +@end cartouche + +Loads a single footprint by name. +@c ./../src/buffer.c 809 + +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. + + +@node LoadFrom Action +@subsection LoadFrom +@c key LoadFrom in hid +@cartouche +@format +LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename)@end format +@end cartouche + +Load layout data from a file. +@c ./../src/action.c 5031 + +This action assumes you know what the filename is. The various GUIs +should have a similar @code{Load} action where the filename is +optional, and will provide their own file selection mechanism to let +you choose the file name. + +@table @code + +@item Layout +Loads an entire PCB layout, replacing the current one. + +@item LayoutToBuffer +Loads an entire PCB layout to the paste buffer. + +@item ElementToBuffer +Loads the given element file into the paste buffer. Element files +contain only a single @code{Element} definition, such as the +``newlib'' library uses. + +@item Netlist +Loads a new netlist, replacing any current netlist. + +@item Revert +Re-loads the current layout from its disk file, reverting any changes +you may have made. + +@end table + + +@node LoadVendorFrom Action +@subsection LoadVendorFrom +@c key LoadVendorFrom in hid +@cartouche +@format +LoadVendorFrom(filename)@end format +@end cartouche + +Loads the specified vendor resource file. +@c ./../src/vendor.c 201 + +@cindex vendor map +@cindex vendor drill table +@findex LoadVendorFrom() + +@table @var +@item filename +Name of the vendor resource file. If not specified, the user will +be prompted to enter one. +@end table + + +@node m Action +@subsection m +@c key m in hid +@cartouche +@format +m [name]@end format +@end cartouche + +Loads a layout into the current buffer. +@c ./../src/command.c 157 + +The filename and the searchpath (@emph{filePath}) are passed to the +command defined by @emph{fileCommand}. +If no filename is specified a file select box will popup. + +@colonaction + + +@node MarkCrosshair Action +@subsection MarkCrosshair +@c key MarkCrosshair in hid +@cartouche +@format +MarkCrosshair() +MarkCrosshair(Center)@end format +@end cartouche + +Set/Reset the Crosshair mark. +@c ./../src/action.c 3502 + +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 @code{Center} argument is given, the mark is moved to the current +cursor location. + + +@node Message Action +@subsection Message +@c key Message in hid +@cartouche +@format +Message(message)@end format +@end cartouche + +Writes a message to the log window. +@c ./../src/action.c 1886 + +This action displays a message to the log window. This action is primarily +provided for use by other programs which may interface with PCB. If +multiple arguments are given, each one is sent to the log window +followed by a newline. + + +@node MinClearGap Action +@subsection MinClearGap +@c key MinClearGap in hid +@cartouche +@format +MinClearGap(delta) +MinClearGap(Selected, delta)@end format +@end cartouche + +Ensures that polygons are a minimum distance from objects. +@c ./../src/action.c 3827 + +Checks all specified objects, and increases the polygon clearance if +needed to ensure a minimum distance between their edges and the +polygon edges. + + +@node MinMaskGap Action +@subsection MinMaskGap +@c key MinMaskGap in hid +@cartouche +@format +MinMaskGap(delta) +MinMaskGap(Selected, delta)@end format +@end cartouche + +Ensures the mask is a minimum distance from pins and pads. +@c ./../src/action.c 3752 + +Checks all specified pins and/or pads, and increases the mask if +needed to ensure a minimum distance between the pin or pad edge and +the mask edge. + + +@node Mode Action +@subsection Mode +@c key Mode in hid +@cartouche +@format +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)@end format +@end cartouche + +Change or use the tool mode. +@c ./../src/action.c 2612 + +@table @code + +@item Arc +@itemx Arrow +@itemx Copy +@itemx InsertPoint +@itemx Line +@itemx Lock +@itemx Move +@itemx None +@itemx PasteBuffer +@itemx Polygon +@itemx Rectangle +@itemx Remove +@itemx Rotate +@itemx Text +@itemx Thermal +@itemx Via +Select the indicated tool. + +@item Notify +Called when you press the mouse button, or move the mouse. + +@item Release +Called when you release the mouse button. + +@item 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. + +@item Escape +Similar to Cancel but calling this action a second time will return +to the Arrow tool. + +@item Stroke +If your @code{pcb} 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. + +@item Save +Remembers the current tool. + +@item Restore +Restores the tool to the last saved tool. + +@end table + + +@node MorphPolygon Action +@subsection MorphPolygon +@c key MorphPolygon in hid +@cartouche +@format +MorphPolygon(Object|Selected)@end format +@end cartouche + +Converts dead polygon islands into separate polygons. +@c ./../src/action.c 4087 + +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. + + +@node MoveLayer Action +@subsection MoveLayer +@c key MoveLayer in hid +@cartouche +@format +MoveLayer(old,new)@end format +@end cartouche + +Moves/Creates/Deletes Layers. +@c ./../src/move.c 1091 + +Moves a layer, creates a new layer, or deletes a layer. + +@table @code + +@item old +The is the layer number to act upon. Allowed values are: +@table @code + +@item c +Currently selected layer. + +@item -1 +Create a new layer. + +@item number +An existing layer number. + +@end table + +@item new +Specifies where to move the layer to. Allowed values are: +@table @code +@item -1 +Deletes the layer. + +@item up +Moves the layer up. + +@item down +Moves the layer down. + +@item c +Creates a new layer. + +@end table + +@end table + + +@node MoveObject Action +@subsection MoveObject +@c key MoveObject in hid +@cartouche +@format +MoveObject(X,Y,dim)@end format +@end cartouche + +Moves the object under the crosshair. +@c ./../src/action.c 5567 + +The @code{X} and @code{Y} are treated like @code{delta} is for many +other objects. For each, if it's prefixed by @code{+} or @code{-}, +then that amount is relative. Otherwise, it's absolute. Units can be +@code{mil} or @code{mm}; if unspecified, units are PCB's internal +units, currently 1/100 mil. + + +@node MoveToCurrentLayer Action +@subsection MoveToCurrentLayer +@c key MoveToCurrentLayer in hid +@cartouche +@format +MoveToCurrentLayer(Object|SelectedObjects)@end format +@end cartouche + +Moves objects to the current layer. +@c ./../src/action.c 5609 + +Note that moving an element from a component layer to a solder layer, +or from solder to component, won't automatically flip it. Use the +@code{Flip()} action to do that. + + +@node Netlist Action +@subsection Netlist +@c key Netlist in hid +@cartouche +@format +Net(find|select|rats|norats|clear[,net[,pin]]) +Net(freeze|thaw|forcethaw) +Net(add,net,pin)@end format +@end cartouche + +Perform various actions on netlists. +@c ./../src/netlist.c 289 + +Each of these actions apply to a specified set of nets. @var{net} and +@var{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, +@emph{then} the pattern is tried as a regular expression. + +If neither @var{net} nor @var{pin} are specified, all nets apply. If +@var{net} is specified but not @var{pin}, all nets matching @var{net} +apply. If both are specified, nets which match @var{net} and contain +a pin matching @var{pin} apply. + +@table @code + +@item find +Nets which apply are marked @emph{found} and are drawn in the +@code{connected-color} color. + +@item select +Nets which apply are selected. + +@item rats +Nets which apply are marked as available for the rats nest. + +@item norats +Nets which apply are marked as not available for the rats nest. + +@item clear +Clears the netlist. + +@item add +Add the given pin to the given netlist, creating either if needed. + +@item sort +Called after a list of add's, this sorts the netlist. + +@item freeze +@itemx thaw +@itemx 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. + +@end table + + +@node New Action +@subsection New +@c key New in hid +@cartouche +@format +New([name])@end format +@end cartouche + +Starts a new layout. +@c ./../src/action.c 5093 + +If a name is not given, one is prompted for. + + +@node OptAutoOnly Action +@subsection OptAutoOnly +@c key OptAutoOnly in hid +@cartouche +@format +OptAutoOnly()@end format +@end cartouche + +Toggles the optimize-only-autorouted flag. +@c ./../src/djopt.c 129 + +The original purpose of the trace optimizer was to clean up the traces +created by the various autorouters that have been used with PCB. When +a board has a mix of autorouted and carefully hand-routed traces, you +don't normally want the optimizer to move your hand-routed traces. +But, sometimes you do. By default, the optimizer only optimizes +autorouted traces. This action toggles that setting, so that you can +optimize hand-routed traces also. + + +@node PasteBuffer Action +@subsection PasteBuffer +@c key PasteBuffer in hid +@cartouche +@format +PasteBuffer(AddSelected|Clear|1..MAX_BUFFER) +PasteBuffer(Rotate, 1..3) +PasteBuffer(Convert|Save|Restore|Mirror) +PasteBuffer(ToLayout, X, Y, units)@end format +@end cartouche + +Various operations on the paste buffer. +@c ./../src/action.c 5153 + +There are a number of paste buffers; the actual limit is a +compile-time constant @code{MAX_BUFFER} in @file{globalconst.h}. It +is currently @code{5}. One of these is the ``current'' paste buffer, +often referred to as ``the'' paste buffer. + +@table @code + +@item AddSelected +Copies the selected objects to the current paste buffer. + +@item Clear +Remove all objects from the current paste buffer. + +@item Convert +Convert the current paste buffer to an element. Vias are converted to +pins, lines are converted to pads. + +@item Restore +Convert any elements in the paste buffer back to vias and lines. + +@item Mirror +Flip all objects in the paste buffer vertically (up/down flip). To mirror +horizontally, combine this with rotations. + +@item 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). + +@item Save +Saves any elements in the current buffer to the indicated file. + +@item ToLayout +Pastes any elements in the current buffer to the indicated X, Y +coordinates in the layout. The @code{X} and @code{Y} are treated like +@code{delta} is for many other objects. For each, if it's prefixed by +@code{+} or @code{-}, then that amount is relative to the last +location. Otherwise, it's absolute. Units can be +@code{mil} or @code{mm}; if unspecified, units are PCB's internal +units, currently 1/100 mil. + + +@item 1..MAX_BUFFER +Selects the given buffer to be the current paste buffer. + +@end table + + +@node Polygon Action +@subsection Polygon +@c key Polygon in hid +@cartouche +@format +Polygon(Close|PreviousPoint)@end format +@end cartouche + +Some polygon related stuff. +@c ./../src/action.c 5503 + +Polygons need a special action routine to make life easier. + +@table @code + +@item 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. + +@item PreviousPoint +Resets the newly entered corner to the previous one. The Undo action +will call Polygon(PreviousPoint) when appropriate to do so. + +@end table + + +@node Puller Action +@subsection Puller +@c key Puller in hid +@cartouche +@format +Puller()@end format +@end cartouche + +Pull an arc-line junction tight. +@c ./../src/puller.c 411 + +The @code{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. In the example below, +the left side is ``before'' with the black target marking where to put +the crosshair: + +@center @image{puller,,,Example of how puller works,png} + +The right side is ``after'' with the black target marking where the +arc-line intersection was moved to. + + +@node q Action +@subsection q +@c key q in hid +@cartouche +@format +q@end format +@end cartouche + +Quits the application after confirming. +@c ./../src/command.c 185 + +If you have unsaved changes, you will be prompted to confirm (or +save) before quitting. + +@colonaction + + +@node q! Action +@subsection q! +@c key q! in hid +@cartouche +@format +q!@end format +@end cartouche + +Quits the application without confirming. +@c ./../src/command.c 199 + +Note that this command neither saves your data nor prompts for +confirmation. + +@colonaction + + +@node Quit Action +@subsection Quit +@c key Quit in hid +@cartouche +@format +Quit()@end format +@end cartouche + +Quits the application after confirming. +@c ./../src/action.c 2071 + +If you have unsaved changes, you will be prompted to confirm (or +save) before quitting. + + +@node Redo Action +@subsection Redo +@c key Redo in hid +@cartouche +@format +Redo()@end format +@end cartouche + +Redo recent``undo''operations. +@c ./../src/action.c 5468 + +This routine 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. + + +@node RemoveSelected Action +@subsection RemoveSelected +@c key RemoveSelected in hid +@cartouche +@format +RemoveSelected()@end format +@end cartouche + +Removes any selected objects. +@c ./../src/action.c 2832 + + +@node Renumber Action +@subsection Renumber +@c key Renumber in hid +@cartouche +@format +Renumber() +Renumber(filename)@end format +@end cartouche + +Renumber all elements. The changes will be recorded to filename +for use in backannotating these changes to the schematic. +@c ./../src/action.c 2848 + + +@node Report Action +@subsection Report +@c key Report in hid +@cartouche +@format +Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])@end format +@end cartouche + +Produce various report. +@c ./../src/report.c 942 + +@table @code + +@item Object +The object under the crosshair will be reported, describing various +aspects of the object. + +@item DrillReport +A report summarizing the number of drill sizes used, and how many of +each, will be produced. + +@item FoundPins +A report listing all pins and pads which are marked as ``found'' will +be produced. + +@item NetLength +The name and length of the net under the crosshair will be reported to +the message log. + +@item 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 + +@end table + + +@node ReportDialog Action +@subsection ReportDialog +@c key ReportDialog in hid +@cartouche +@format +ReportDialog()@end format +@end cartouche + +Report on the object under the crosshair +@c ./../src/report.c 125 + +This is a shortcut for @code{Report(Object)}. + + +@node RipUp Action +@subsection RipUp +@c key RipUp in hid +@cartouche +@format +RipUp(All|Selected|Element)@end format +@end cartouche + +Ripup auto-routed tracks, or convert an element to parts. +@c ./../src/action.c 3199 + +@table @code + +@item All +Removes all lines and vias which were created by the autorouter. + +@item Selected +Removes all selected lines and vias which were created by the +autorouter. + +@item Element +Converts the element under the cursor to parts (vias and lines). Note +that this uses the highest numbered paste buffer. + +@end table + + +@node rn Action +@subsection rn +@c key rn in hid +@cartouche +@format +rn [name]@end format +@end cartouche + +Reads netlist. +@c ./../src/command.c 214 + +If no filename is given a file select box will pop up. The file is +read via the command defined by the @emph{RatCommand} resource. The +command must send its output to @emph{stdout}. + +Netlists are used for generating rat's nests (see @ref{Rats Nest}) and +for verifying the board layout (which is also accomplished by the +@emph{Ratsnest} command). + +@colonaction + + +@node RouteStyle Action +@subsection RouteStyle +@c key RouteStyle in hid +@cartouche +@format +RouteStyle(1|2|3|4)@end format +@end cartouche + +Copies the indicated routing style into the current sizes. +@c ./../src/action.c 5535 + + +@node s Action +@subsection s +@c key s in hid +@cartouche +@format +s [name]@end format +@end cartouche + +Saves layout data. +@c ./../src/command.c 244 + +Data and the filename are passed to the command defined by the +resource @emph{saveCommand}. It must read the layout data from +@emph{stdin}. 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. + +@colonaction + + +@node SaveSettings Action +@subsection SaveSettings +@c key SaveSettings in hid +@cartouche +@format +SaveSettings() +SaveSettings(local)@end format +@end cartouche + +Saves settings. +@c ./../src/action.c 5015 + +If you pass no arguments, the settings are stored in +@code{$HOME/.pcb/settings}. If you pass the word @code{local} they're +saved in @code{./pcb.settings}. + + +@node SaveTo Action +@subsection SaveTo +@c key SaveTo in hid +@cartouche +@format +SaveTo(Layout|LayoutAs,filename) +SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename) +SaveTo(PasteBuffer,filename)@end format +@end cartouche + +Saves data to a file. +@c ./../src/action.c 4919 + +@table @code + +@item Layout +Saves the current layout. + +@item LayoutAs +Saves the current layout, and remembers the filename used. + +@item AllConnections +Save all connections to a file. + +@item AllUnusedPins +List all unused pins to a file. + +@item ElementConnections +Save connections to the element at the cursor to a file. + +@item PasteBuffer +Save the content of the active Buffer to a file. This is the graphical way to create a footprint. + +@end table + + +@node Select Action +@subsection Select +@c key Select in hid +@cartouche +@format +Select(Object|ToggleObject) +Select(All|Block|Connection) +Select(ElementByName|ObjectByName|PadByName|PinByName) +Select(ElementByName|ObjectByName|PadByName|PinByName, Name) +Select(TextByName|ViaByName|NetByName) +Select(TextByName|ViaByName|NetByName, Name) +Select(Convert)@end format +@end cartouche + +Toggles or sets the selection. +@c ./../src/action.c 4651 + +@table @code + +@item ElementByName +@item ObjectByName +@item PadByName +@item PinByName +@item TextByName +@item ViaByName +@item NetByName + +These all rely on having a regular expression parser built into +@code{pcb}. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are selected. + +@item Object +@item ToggleObject +Selects the object under the cursor. + +@item Block +Selects all objects in a rectangle indicated by the cursor. + +@item All +Selects all objects on the board. + +@item Connection +Selects all connections with the ``found'' flag set. + +@item Convert +Converts the selected objects to an element. This uses the highest +numbered paste buffer. + +@end table + + +@node SetFlag Action +@subsection SetFlag +@c key SetFlag in hid +@cartouche +@format +SetFlag(Object|Selected|SelectedObjects, flag) +SetFlag(SelectedLines|SelectedPins|SelectedVias, flag) +SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag) +SetFlag(SelectedElements, flag) +flag = square | octagon | thermal | join@end format +@end cartouche + +Sets flags on objects. +@c ./../src/action.c 5716 + +Turns the given flag on, regardless of its previous setting. See +@code{ChangeFlag}. + +@example +SetFlag(SelectedPins,thermal) +@end example + + +@node SetOctagon Action +@subsection SetOctagon +@c key SetOctagon in hid +@cartouche +@format +SetOctagon(Object|ToggleObject|SelectedElements|Selected)@end format +@end cartouche + +Sets the octagon-flag of objects. +@c ./../src/action.c 4459 + +@pinshapes + + +@node SetSame Action +@subsection SetSame +@c key SetSame in hid +@cartouche +@format +SetSame()@end format +@end cartouche + +Sets current layer and sizes to match indicated item. +@c ./../src/action.c 5648 + +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, keepaway, drill, etc) according to that item. + + +@node SetSquare Action +@subsection SetSquare +@c key SetSquare in hid +@cartouche +@format +SetSquare(ToggleObject|SelectedElements|SelectedPins)@end format +@end cartouche + +sets the square-flag of objects. +@c ./../src/action.c 4301 + +Note that @code{Pins} means pins and pads. + +@pinshapes + + +@node SetThermal Action +@subsection SetThermal +@c key SetThermal in hid +@cartouche +@format +SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)@end format +@end cartouche + +Set the thermal (on the current layer) of pins or vias 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. + +@c ./../src/action.c 1912 + +This changes how/whether pins or vias connect to any rectangle or polygon +on the current layer. The first argument can specify one object, or all +selected pins, or all selected vias, or all selected pins and vias. +The second argument specifies the style of connection. +There are 5 possibilities: +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. + +Pins and Vias may have thermals whether or not there is a polygon available +to connect with. However, they will have no effect without the polygon. + +@node SetValue Action +@subsection SetValue +@c key SetValue in hid +@cartouche +@format +SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)@end format +@end cartouche + +Change various board-wide values and sizes. +@c ./../src/action.c 1996 + +@table @code + +@item ViaDrillingHole +Changes the diameter of the drill for new vias. + +@item Grid +Sets the grid spacing. + +@item Line +@item LineSize +Changes the thickness of new lines. + +@item Via +@item ViaSize +Changes the diameter of new vias. + +@item Text +@item TextScale +Changes the size of new text. + +@end table + + +@node ToggleHideName Action +@subsection ToggleHideName +@c key ToggleHideName in hid +@cartouche +@format +ToggleHideName(Object|SelectedElements)@end format +@end cartouche + +Toggles the visibility of element names. +@c ./../src/action.c 4134 + +If names are hidden you won't see them on the screen and they will not +appear on the silk layer when you print the layout. + + +@node ToggleVendor Action +@subsection ToggleVendor +@c key ToggleVendor in hid +@cartouche +@format +ToggleVendor()@end format +@end cartouche + +Toggles the state of automatic drill size mapping. +@c ./../src/vendor.c 128 + +@cindex vendor map +@cindex vendor drill table +@findex ToggleVendor() + +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. To enable drill +mapping, a vendor resource file containing a drill table must be +loaded first. + + +@node Undo Action +@subsection Undo +@c key Undo in hid +@cartouche +@format +Undo() +Undo(ClearList)@end format +@end cartouche + +Undo recent changes. +@c ./../src/action.c 5304 + +The unlimited undo feature of @code{Pcb} allows you to recover from +most operations that materially affect you work. Calling +@code{Undo()} without any parameter recovers from the last (non-undo) +operation. @code{ClearList} is used to release the allocated +memory. @code{ClearList} is called whenever a new layout is started or +loaded. See also @code{Redo} and @code{Atomic}. + +Note that undo groups operations by serial number; changes with the +same serial number will be undone (or redone) as a group. See +@code{Atomic}. + + +@node UnloadVendor Action +@subsection UnloadVendor +@c key UnloadVendor in hid +@cartouche +@format +UnloadVendor()@end format +@end cartouche + +Unloads the current vendor drill mapping table. +@c ./../src/vendor.c 176 + +@cindex vendor map +@cindex vendor drill table +@findex UnloadVendor() + + +@node Unselect Action +@subsection Unselect +@c key Unselect in hid +@cartouche +@format +Unselect(All|Block|Connection) +Unselect(ElementByName|ObjectByName|PadByName|PinByName) +Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name) +Unselect(TextByName|ViaByName) +Unselect(TextByName|ViaByName, Name) +@end format +@end cartouche + +Unselects the object at the pointer location or the specified objects. +@c ./../src/action.c 4803 + +@table @code + +@item All +Unselect all objects. + +@item Block +Unselect all objects in a rectangle given by the cursor. + +@item Connection +Unselect all connections with the ``found'' flag set. + +@item ElementByName +@item ObjectByName +@item PadByName +@item PinByName +@item TextByName +@item ViaByName + +These all rely on having a regular expression parser built into +@code{pcb}. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are unselected. + + +@end table + + +@node w Action +@subsection w +@c key w in hid +@cartouche +@format +w [name]@end format +@end cartouche + +Saves layout data. +@c ./../src/command.c 250 + +This commands has been added for the convenience of @code{vi} users +and has the same functionality as @code{s}. + +@colonaction + + +@node wq Action +@subsection wq +@c key wq in hid +@cartouche +@format +wq@end format +@end cartouche + +Saves the layout data and quits. +@c ./../src/command.c 291 + +This command has been added for the convenience of @code{vi} users and +has the same functionality as @code{s} combined with @code{q}. + +@colonaction + + +@node common actions +@section common actions +@c ./../src/hid/common/actions.c 425 + +@macro hidaction + +This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +@end macro + +@menu +* LayersChanged Action:: Tells the GUI that the layers have changed. +* LibraryChanged Action:: Tells the GUI that the libraries have changed. +* NetlistChanged Action:: Tells the GUI that the netlist has changed. +* PCBChanged Action:: Tells 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 settings +* RouteStylesChanged Action:: Tells the GUI that the routing styles have changed. +@end menu +@node LayersChanged Action +@subsection LayersChanged +@c key LayersChanged in hid common +@cartouche +@format +LayersChanged()@end format +@end cartouche + +Tells the GUI that the layers have changed. +@c ./../src/hid/common/actions.c 446 + +This includes layer names, colors, stacking order, visibility, etc. + +@hidaction + + +@node LibraryChanged Action +@subsection LibraryChanged +@c key LibraryChanged in hid common +@cartouche +@format +LibraryChanged()@end format +@end cartouche + +Tells the GUI that the libraries have changed. +@c ./../src/hid/common/actions.c 451 + +@hidaction + + +@node NetlistChanged Action +@subsection NetlistChanged +@c key NetlistChanged in hid common +@cartouche +@format +NetlistChanged()@end format +@end cartouche + +Tells the GUI that the netlist has changed. +@c ./../src/hid/common/actions.c 441 + +@hidaction + + +@node PCBChanged Action +@subsection PCBChanged +@c key PCBChanged in hid common +@cartouche +@format +PCBChanged([revert])@end format +@end cartouche + +Tells 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 settings +@c ./../src/hid/common/actions.c 431 + +@hidaction + + +@node RouteStylesChanged Action +@subsection RouteStylesChanged +@c key RouteStylesChanged in hid common +@cartouche +@format +RouteStylesChanged()@end format +@end cartouche + +Tells the GUI that the routing styles have changed. +@c ./../src/hid/common/actions.c 436 + +@hidaction + + +@node gtk actions +@section gtk actions +@menu +* gtk About Action:: N_("Tell the user about this version of PCB."); +* gtk AdjustStyle Action:: Open the window which allows editing of the route styles. +* gtk Center Action:: N_("Moves the pointer to the center of the window."); +* gtk Cursor Action:: N_("Move the cursor."); +* gtk DoWindows Action:: N_("Open various GUI windows."); +* gtk EditLayerGroups Action:: Open the preferences window which allows editing of the layer groups. +* gtk GetXY Action:: N_("Get a coordinate."); +* gtk ImportGUI Action:: N_("Asks user which schematics to import into PCB. +"); +* gtk Pan Action:: N_("Start or stop panning (Mode = 1 to start, 0 to stop) +Optional thumb argument is ignored for now in gtk hid. +"); +* gtk Popup Action:: N_("Bring up the popup menu specified by @code{MenuName}. +If called by a mouse event then the mouse button number +must be specified as the optional second argument."); +* gtk Print Action:: N_("Print the layout."); +* gtk PrintCalibrate Action:: N_("Calibrate the printer."); +* gtk Save Action:: N_("Save layout and/or element data to a user-selected file."); +* gtk SelectLayer Action:: Select which layer is the current layer. +* gtk SetUnits Action:: N_("Set the default measurement units."); +* gtk SwapSides Action:: N_("Swaps the side of the board you're looking at."); +* gtk ToggleView Action:: Toggle the visibility of the specified layer or layer group. +* gtk Zoom Action:: N_("Various zoom factor changes."); +@end menu +@node gtk About Action +@subsection gtk About +@c key gtk About in hid gtk +@cartouche +@format +About()@end format +@end cartouche + +N_("Tell the user about this version of PCB."); +@c ./../src/hid/gtk/gtkhid-main.c 1059 + +This just pops up a dialog telling the user which version of +@code{pcb} they're running. + + +@node gtk AdjustStyle Action +@subsection gtk AdjustStyle +@c key gtk AdjustStyle in hid gtk +@cartouche +@format +AdjustStyle() +@end format +@end cartouche + +Open the window which allows editing of the route styles. +@c ./../src/hid/gtk/gui-top-window.c 2081 + +Opens the window which allows editing of the route styles. + + +@node gtk Center Action +@subsection gtk Center +@c key gtk Center in hid gtk +@cartouche +@format +Center() +@end format +@end cartouche + +N_("Moves the pointer to the center of the window."); +@c ./../src/hid/gtk/gtkhid-main.c 1470 + +Move the pointer to the center of the window, but only if it's +currently within the window already. + + +@node gtk Cursor Action +@subsection gtk Cursor +@c key gtk Cursor in hid gtk +@cartouche +@format +Cursor(Type,DeltaUp,DeltaRight,Units)@end format +@end cartouche + +N_("Move the cursor."); +@c ./../src/hid/gtk/gtkhid-main.c 1515 + +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 @var{DeltaUp} may move the +cursor towards the board origin if the board is inverted. + +Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the +viewport to move such that the crosshair is under the mouse cursor. +@samp{Warp} causes the mouse cursor to move to be above the crosshair. + +@var{Units} can be one of the following: + +@table @samp + +@item mil +@itemx mm +The cursor is moved by that amount, in board units. + +@item grid +The cursor is moved by that many grid points. + +@item view +The values are percentages of the viewport's view. Thus, a pan of +@samp{100} would scroll the viewport by exactly the width of the +current view. + +@item board +The values are percentages of the board size. Thus, a move of +@samp{50,50} moves you halfway across the board. + +@end table + + +@node gtk DoWindows Action +@subsection gtk DoWindows +@c key gtk DoWindows in hid gtk +@cartouche +@format +DoWindows(1|2|3|4|5|6) +DoWindows(Layout|Library|Log|Netlist|Preferences|DRC)@end format +@end cartouche + +N_("Open various GUI windows."); +@c ./../src/hid/gtk/gtkhid-main.c 1563 + +@table @code + +@item 1 +@itemx Layout +Open the layout window. Since the layout window is always shown +anyway, this has no effect. + +@item 2 +@itemx Library +Open the library window. + +@item 3 +@itemx Log +Open the log window. + +@item 4 +@itemx Netlist +Open the netlist window. + +@item 5 +@itemx Preferences +Open the preferences window. + +@item 6 +@itemx DRC +Open the DRC violations window. + +@end table + + +@node gtk EditLayerGroups Action +@subsection gtk EditLayerGroups +@c key gtk EditLayerGroups in hid gtk +@cartouche +@format +EditLayerGroups() +@end format +@end cartouche + +Open the preferences window which allows editing of the layer groups. +@c ./../src/hid/gtk/gui-top-window.c 2100 + +Opens the preferences window which is where the layer groups +are edited. This action is primarily provides to provide menu +resource compatibility with the lesstif HID. + + +@node gtk GetXY Action +@subsection gtk GetXY +@c key gtk GetXY in hid gtk +@cartouche +@format +GetXY()@end format +@end cartouche + +N_("Get a coordinate."); +@c ./../src/hid/gtk/gtkhid-main.c 1074 + +Prompts the user for a coordinate, if one is not already selected. + + +@node gtk ImportGUI Action +@subsection gtk ImportGUI +@c key gtk ImportGUI in hid gtk +@cartouche +@format +ImportGUI()@end format +@end cartouche + +N_("Asks user which schematics to import into PCB. +"); +@c ./../src/hid/gtk/gtkhid-main.c 1750 + +Asks user which schematics to import into PCB. + + +@node gtk Pan Action +@subsection gtk Pan +@c key gtk Pan in hid gtk +@cartouche +@format +Pan([thumb], Mode)@end format +@end cartouche + +N_("Start or stop panning (Mode = 1 to start, 0 to stop) +Optional thumb argument is ignored for now in gtk hid. +"); +@c ./../src/hid/gtk/gtkhid-main.c 1687 + +Start or stop panning. To start call with Mode = 1, to stop call with +Mode = 0. + + +@node gtk Popup Action +@subsection gtk Popup +@c key gtk Popup in hid gtk +@cartouche +@format +Popup(MenuName, [Button])@end format +@end cartouche + +N_("Bring up the popup menu specified by @code{MenuName}. +If called by a mouse event then the mouse button number +must be specified as the optional second argument."); +@c ./../src/hid/gtk/gtkhid-main.c 1719 + +This just pops up the specified menu. The menu must have been defined +as a named subresource of the Popups resource in the menu resource +file. + + +@node gtk Print Action +@subsection gtk Print +@c key gtk Print in hid gtk +@cartouche +@format +Print()@end format +@end cartouche + +N_("Print the layout."); +@c ./../src/hid/gtk/gtkhid-main.c 1350 + +This will find the default printing HID, prompt the user for its +options, and print the layout. + + +@node gtk PrintCalibrate Action +@subsection gtk PrintCalibrate +@c key gtk PrintCalibrate in hid gtk +@cartouche +@format +PrintCalibrate()@end format +@end cartouche + +N_("Calibrate the printer."); +@c ./../src/hid/gtk/gtkhid-main.c 1401 + +This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. + + +@node gtk Save Action +@subsection gtk Save +@c key gtk Save in hid gtk +@cartouche +@format +Save() +Save(Layout|LayoutAs) +Save(AllConnections|AllUnusedPins|ElementConnections) +Save(PasteBuffer)@end format +@end cartouche + +N_("Save layout and/or element data to a user-selected file."); +@c ./../src/hid/gtk/gtkhid-main.c 1230 + +This action is a GUI front-end to the core's @code{SaveTo} action +(@pxref{SaveTo Action}). If you happen to pass a filename, like +@code{SaveTo}, then @code{SaveTo} is called directly. Else, the +user is prompted for a filename to save, and then @code{SaveTo} is +called with that filename. + + +@node gtk SelectLayer Action +@subsection gtk SelectLayer +@c key gtk SelectLayer in hid gtk +@cartouche +@format +SelectLayer(1..MAXLAYER|Silk|Rats)@end format +@end cartouche + +Select which layer is the current layer. +@c ./../src/hid/gtk/gui-top-window.c 1851 + +The specified layer becomes the currently active layer. It is made +visible if it is not already visible + + +@node gtk SetUnits Action +@subsection gtk SetUnits +@c key gtk SetUnits in hid gtk +@cartouche +@format +SetUnits(mm|mil)@end format +@end cartouche + +N_("Set the default measurement units."); +@c ./../src/hid/gtk/gtkhid-main.c 1606 + +@table @code + +@item mil +Sets the display units to mils (1/1000 inch). + +@item mm +Sets the display units to millimeters. + +@end table + + +@node gtk SwapSides Action +@subsection gtk SwapSides +@c key gtk SwapSides in hid gtk +@cartouche +@format +SwapSides(|v|h|r)@end format +@end cartouche + +N_("Swaps the side of the board you're looking at."); +@c ./../src/hid/gtk/gtkhid-main.c 1295 + +This action changes the way you view the board. + +@table @code + +@item v +Flips the board over vertically (up/down). + +@item h +Flips the board over horizontally (left/right), like flipping pages in +a book. + +@item r +Rotates the board 180 degrees without changing sides. + +@end table + +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 +true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. + +As a special case, 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. + + +@node gtk ToggleView Action +@subsection gtk ToggleView +@c key gtk ToggleView in hid gtk +@cartouche +@format +ToggleView(1..MAXLAYER) +ToggleView(layername) +ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)@end format +@end cartouche + +Toggle the visibility of the specified layer or layer group. +@c ./../src/hid/gtk/gui-top-window.c 1792 + +If you pass an integer, that layer is specified by index (the first +layer is @code{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. + + +@node gtk Zoom Action +@subsection gtk Zoom +@c key gtk Zoom in hid gtk +@cartouche +@format +Zoom() +Zoom(factor)@end format +@end cartouche + +N_("Various zoom factor changes."); +@c ./../src/hid/gtk/gtkhid-main.c 161 +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, +@var{factor} specifies a change in zoom factor. It may be prefixed by +@code{+}, @code{-}, or @code{=} to change how the zoom factor is +modified. The @var{factor} is a floating point number, such as +@code{1.5} or @code{0.75}. + +@table @code + +@item +@var{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. + +@item -@var{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. + +@item =@var{factor} + +The @var{factor} is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +@var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a @var{factor} of 100 gives you a 10x actual +size. + +@end table + +Note that zoom factors of zero are silently ignored. + + + + +@node lesstif actions +@section lesstif actions +@menu +* lesstif About Action:: Tell the user about this version of PCB. +* lesstif AdjustSizes Action:: Let the user change the board size, DRC parameters, etc +* lesstif AdjustStyle Action:: Displays the route style adjustment window. +* lesstif Benchmark Action:: Benchmark the GUI speed. +* lesstif Command Action:: Displays the command line input window. +* lesstif Cursor Action:: Move the cursor. +* lesstif Debug Action:: Debug action. +* lesstif DebugXY Action:: Debug action, with coordinates +* lesstif DoWindows Action:: Open various GUI windows. +* lesstif DumpKeys Action:: Dump Lesstif key bindings. +* lesstif EditLayerGroups Action:: Let the user change the layer groupings +* lesstif Export Action:: Export the layout. +* lesstif GetXY Action:: Get a coordinate. +* lesstif ImportGUI Action:: Lets the user choose the schematics to import from +* lesstif LibraryShow Action:: Displays the library window. +* lesstif Load Action:: Load layout data from a user-selected file. +* lesstif LoadVendor Action:: Loads a user-selected vendor resource file. +* lesstif NetlistShow Action:: Selects the given pinname or netname in the netlist window. +* lesstif Print Action:: Print the layout. +* lesstif PrintCalibrate Action:: Calibrate the printer. +* lesstif PromptFor Action:: Prompt for a response. +* lesstif Return Action:: Simulate a passing or failing action. +* lesstif Save Action:: Save layout data to a user-selected file. +* lesstif SelectLayer Action:: Select which layer is the current layer. +* lesstif SetUnits Action:: Set the default measurement units. +* lesstif SwapSides Action:: Swaps the side of the board you're looking at. +* lesstif ToggleView Action:: Toggle the visibility of the specified layer or layer group. +* lesstif Zoom Action:: Various zoom factor changes. +@end menu +@node lesstif About Action +@subsection lesstif About +@c key lesstif About in hid lesstif +@cartouche +@format +About()@end format +@end cartouche + +Tell the user about this version of PCB. +@c ./../src/hid/lesstif/dialogs.c 867 + +This just pops up a dialog telling the user which version of +@code{pcb} they're running. + + +@node lesstif AdjustSizes Action +@subsection lesstif AdjustSizes +@c key lesstif AdjustSizes in hid lesstif +@cartouche +@format +AdjustSizes()@end format +@end cartouche + +Let the user change the board size, DRC parameters, etc +@c ./../src/hid/lesstif/dialogs.c 1136 + +Displays a dialog box that lets the user change the board +size, DRC parameters, and text scale. + +The units are determined by the default display units. + + +@node lesstif AdjustStyle Action +@subsection lesstif AdjustStyle +@c key lesstif AdjustStyle in hid lesstif +@cartouche +@format +AdjustStyle()@end format +@end cartouche + +Displays the route style adjustment window. +@c ./../src/hid/lesstif/styles.c 344 + + +@node lesstif Benchmark Action +@subsection lesstif Benchmark +@c key lesstif Benchmark in hid lesstif +@cartouche +@format +Benchmark()@end format +@end cartouche + +Benchmark the GUI speed. +@c ./../src/hid/lesstif/main.c 659 + +This action is used to speed-test the Lesstif graphics subsystem. 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. + + +@node lesstif Command Action +@subsection lesstif Command +@c key lesstif Command in hid lesstif +@cartouche +@format +Command()@end format +@end cartouche + +Displays the command line input window. +@c ./../src/hid/lesstif/main.c 644 + +The command window allows the user to manually enter actions to be +executed. Action syntax can be done one of two ways: + +@table @code + +@item +Follow the action name by an open parenthesis, arguments separated by +commas, end with a close parenthesis. Example: @code{Abc(1,2,3)} + +@item +Separate the action name and arguments by spaces. Example: @code{Abc +1 2 3}. + +@end table + +The first option allows you to have arguments with spaces in them, +but the second is more ``natural'' to type for most people. + +Note that action names are not case sensitive, but arguments normally +are. However, most actions will check for ``keywords'' in a case +insensitive way. + +There are three ways to finish with the command window. If you press +the @code{Enter} key, the command is invoked, the window goes away, +and the next time you bring up the command window it's empty. If you +press the @code{Esc} key, the window goes away without invoking +anything, and the next time you bring up the command window it's +empty. If you change focus away from the command window (i.e. click +on some other window), the command window goes away but the next time +you bring it up it resumes entering the command you were entering +before. + + +@node lesstif Cursor Action +@subsection lesstif Cursor +@c key lesstif Cursor in hid lesstif +@cartouche +@format +Cursor(Type,DeltaUp,DeltaRight,Units)@end format +@end cartouche + +Move the cursor. +@c ./../src/hid/lesstif/main.c 716 + +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 @var{DeltaUp} may move the +cursor towards the board origin if the board is inverted. + +Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the +viewport to move such that the crosshair is under the mouse cursor. +@samp{Warp} causes the mouse cursor to move to be above the crosshair. + +@var{Units} can be one of the following: + +@table @samp + +@item mil +@itemx mm +The cursor is moved by that amount, in board units. + +@item grid +The cursor is moved by that many grid points. + +@item view +The values are percentages of the viewport's view. Thus, a pan of +@samp{100} would scroll the viewport by exactly the width of the +current view. + +@item board +The values are percentages of the board size. Thus, a move of +@samp{50,50} moves you halfway across the board. + +@end table + + +@node lesstif Debug Action +@subsection lesstif Debug +@c key lesstif Debug in hid lesstif +@cartouche +@format +Debug(...)@end format +@end cartouche + +Debug action. +@c ./../src/hid/lesstif/menu.c 66 + +This action exists to help debug scripts; it simply prints all its +arguments to stdout. + + +@node lesstif DebugXY Action +@subsection lesstif DebugXY +@c key lesstif DebugXY in hid lesstif +@cartouche +@format +DebugXY(...)@end format +@end cartouche + +Debug action, with coordinates +@c ./../src/hid/lesstif/menu.c 72 + +Like @code{Debug}, but requires a coordinate. If the user hasn't yet +indicated a location on the board, the user will be prompted to click +on one. + + +@node lesstif DoWindows Action +@subsection lesstif DoWindows +@c key lesstif DoWindows in hid lesstif +@cartouche +@format +DoWindows(1|2|3|4) +DoWindows(Layout|Library|Log|Netlist)@end format +@end cartouche + +Open various GUI windows. +@c ./../src/hid/lesstif/dialogs.c 831 + +@table @code + +@item 1 +@itemx Layout +Open the layout window. Since the layout window is always shown +anyway, this has no effect. + +@item 2 +@itemx Library +Open the library window. + +@item 3 +@itemx Log +Open the log window. + +@item 4 +@itemx Netlist +Open the netlist window. + +@end table + + +@node lesstif DumpKeys Action +@subsection lesstif DumpKeys +@c key lesstif DumpKeys in hid lesstif +@cartouche +@format +DumpKeys()@end format +@end cartouche + +Dump Lesstif key bindings. +@c ./../src/hid/lesstif/menu.c 101 + +Causes the list of key bindings (from @code{pcb-menu.res}) to be +dumped to stdout. This is most useful when invoked from the command +line like this: + +@example +pcb --action-string DumpKeys +@end example + + +@node lesstif EditLayerGroups Action +@subsection lesstif EditLayerGroups +@c key lesstif EditLayerGroups in hid lesstif +@cartouche +@format +EditLayerGroups()@end format +@end cartouche + +Let the user change the layer groupings +@c ./../src/hid/lesstif/dialogs.c 1448 + +Displays a dialog that lets the user view and change the layer +groupings. Each layer (row) can be a member of any one layer group +(column). Note the special layers @code{solder} and @code{component} +allow you to specify which groups represent the top and bottom of the +board. + +See @ref{ChangeName Action}. + + +@node lesstif Export Action +@subsection lesstif Export +@c key lesstif Export in hid lesstif +@cartouche +@format +Export()@end format +@end cartouche + +Export the layout. +@c ./../src/hid/lesstif/dialogs.c 957 + +Prompts the user for an exporter to use. Then, prompts the user for +that exporter's options, and exports the layout. + + +@node lesstif GetXY Action +@subsection lesstif GetXY +@c key lesstif GetXY in hid lesstif +@cartouche +@format +GetXY()@end format +@end cartouche + +Get a coordinate. +@c ./../src/hid/lesstif/menu.c 54 + +Prompts the user for a coordinate, if one is not already selected. + + +@node lesstif ImportGUI Action +@subsection lesstif ImportGUI +@c key lesstif ImportGUI in hid lesstif +@cartouche +@format +ImportGUI()@end format +@end cartouche + +Lets the user choose the schematics to import from +@c ./../src/hid/lesstif/dialogs.c 1882 + +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. + + +@node lesstif LibraryShow Action +@subsection lesstif LibraryShow +@c key lesstif LibraryShow in hid lesstif +@cartouche +@format +LibraryShow()@end format +@end cartouche + +Displays the library window. +@c ./../src/hid/lesstif/library.c 151 + + +@node lesstif Load Action +@subsection lesstif Load +@c key lesstif Load in hid lesstif +@cartouche +@format +Load() +Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)@end format +@end cartouche + +Load layout data from a user-selected file. +@c ./../src/hid/lesstif/dialogs.c 99 + +This action is a GUI front-end to the core's @code{LoadFrom} action +(@pxref{LoadFrom Action}). If you happen to pass a filename, like +@code{LoadFrom}, then @code{LoadFrom} is called directly. Else, the +user is prompted for a filename to load, and then @code{LoadFrom} is +called with that filename. + + +@node lesstif LoadVendor Action +@subsection lesstif LoadVendor +@c key lesstif LoadVendor in hid lesstif +@cartouche +@format +LoadVendor()@end format +@end cartouche + +Loads a user-selected vendor resource file. +@c ./../src/hid/lesstif/dialogs.c 152 + +The user is prompted for a file to load, and then +@code{LoadVendorFrom} is called (@pxref{LoadVendorFrom Action}) to +load that vendor file. + + +@node lesstif NetlistShow Action +@subsection lesstif NetlistShow +@c key lesstif NetlistShow in hid lesstif +@cartouche +@format +NetlistShow(pinname|netname)@end format +@end cartouche + +Selects the given pinname or netname in the netlist window. +@c ./../src/hid/lesstif/netlist.c 415 + + +@node lesstif Print Action +@subsection lesstif Print +@c key lesstif Print in hid lesstif +@cartouche +@format +Print()@end format +@end cartouche + +Print the layout. +@c ./../src/hid/lesstif/dialogs.c 894 + +This will find the default printing HID, prompt the user for its +options, and print the layout. + + +@node lesstif PrintCalibrate Action +@subsection lesstif PrintCalibrate +@c key lesstif PrintCalibrate in hid lesstif +@cartouche +@format +PrintCalibrate()@end format +@end cartouche + +Calibrate the printer. +@c ./../src/hid/lesstif/dialogs.c 937 + +This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. + + +@node lesstif PromptFor Action +@subsection lesstif PromptFor +@c key lesstif PromptFor in hid lesstif +@cartouche +@format +PromptFor([message[,default]])@end format +@end cartouche + +Prompt for a response. +@c ./../src/hid/lesstif/dialogs.c 560 + +This is mostly for testing the lesstif HID interface. The parameters +are passed to the @code{prompt_for()} HID function, causing the user +to be prompted for a response. The respose is simply printed to the +user's stdout. + + +@node lesstif Return Action +@subsection lesstif Return +@c key lesstif Return in hid lesstif +@cartouche +@format +Return(0|1)@end format +@end cartouche + +Simulate a passing or failing action. +@c ./../src/hid/lesstif/menu.c 89 + +This is for testing. If passed a 0, does nothing and succeeds. If +passed a 1, does nothing but pretends to fail. + + +@node lesstif Save Action +@subsection lesstif Save +@c key lesstif Save in hid lesstif +@cartouche +@format +Save() +Save(Layout|LayoutAs) +Save(AllConnections|AllUnusedPins|ElementConnections) +Save(PasteBuffer)@end format +@end cartouche + +Save layout data to a user-selected file. +@c ./../src/hid/lesstif/dialogs.c 197 + +This action is a GUI front-end to the core's @code{SaveTo} action +(@pxref{SaveTo Action}). If you happen to pass a filename, like +@code{SaveTo}, then @code{SaveTo} is called directly. Else, the +user is prompted for a filename to save, and then @code{SaveTo} is +called with that filename. + + +@node lesstif SelectLayer Action +@subsection lesstif SelectLayer +@c key lesstif SelectLayer in hid lesstif +@cartouche +@format +SelectLayer(1..MAXLAYER|Silk|Rats)@end format +@end cartouche + +Select which layer is the current layer. +@c ./../src/hid/lesstif/menu.c 387 + +The specified layer becomes the currently active layer. It is made +visible if it is not already visible + + +@node lesstif SetUnits Action +@subsection lesstif SetUnits +@c key lesstif SetUnits in hid lesstif +@cartouche +@format +SetUnits(mm|mil)@end format +@end cartouche + +Set the default measurement units. +@c ./../src/hid/lesstif/main.c 395 + +@table @code + +@item mil +Sets the display units to mils (1/1000 inch). + +@item mm +Sets the display units to millimeters. + +@end table + + +@node lesstif SwapSides Action +@subsection lesstif SwapSides +@c key lesstif SwapSides in hid lesstif +@cartouche +@format +SwapSides(|v|h|r)@end format +@end cartouche + +Swaps the side of the board you're looking at. +@c ./../src/hid/lesstif/main.c 494 + +This action changes the way you view the board. + +@table @code + +@item v +Flips the board over vertically (up/down). + +@item h +Flips the board over horizontally (left/right), like flipping pages in +a book. + +@item r +Rotates the board 180 degrees without changing sides. + +@end table + +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 +true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. + +As a special case, 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. + + +@node lesstif ToggleView Action +@subsection lesstif ToggleView +@c key lesstif ToggleView in hid lesstif +@cartouche +@format +ToggleView(1..MAXLAYER) +ToggleView(layername) +ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)@end format +@end cartouche + +Toggle the visibility of the specified layer or layer group. +@c ./../src/hid/lesstif/menu.c 409 + +If you pass an integer, that layer is specified by index (the first +layer is @code{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. + + +@node lesstif Zoom Action +@subsection lesstif Zoom +@c key lesstif Zoom in hid lesstif +@cartouche +@format +Zoom() +Zoom(factor)@end format +@end cartouche + +Various zoom factor changes. +@c ./../src/hid/lesstif/main.c 419 + +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, +@var{factor} specifies a change in zoom factor. It may be prefixed by +@code{+}, @code{-}, or @code{=} to change how the zoom factor is +modified. The @var{factor} is a floating point number, such as +@code{1.5} or @code{0.75}. + +@table @code + +@item +@var{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. + +@item -@var{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. + +@item =@var{factor} + +The @var{factor} is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +@var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a @var{factor} of 100 gives you a 10x actual +size. + +@end table + +Note that zoom factors of zero are silently ignored. + + Index: tags/1.2.7/doc-orig/eps2png =================================================================== --- tags/1.2.7/doc-orig/eps2png (nonexistent) +++ tags/1.2.7/doc-orig/eps2png (revision 13657) @@ -0,0 +1,495 @@ +#!/usr/bin/perl + +my $RCS_Id = '$Id$ '; + +# Author : Johan Vromans +# Created On : Tue Sep 15 15:59:04 1992 +# Last Modified By: Johan Vromans +# Last Modified On: Sun Jun 24 17:07:29 2001 +# Update Count : 155 +# Status : Okay + +################ Common stuff ################ + +use strict; +use Getopt::Long 2.1; + +my $my_package = "Sciurix"; +my ($my_name, $my_version) = $RCS_Id =~ /: (.+).pl,v ([\d.]+)/; +$my_version .= '*' if length('$Locker$ ') > 12; + +use vars qw($VERSION); +( $VERSION ) = '$Revision$ ' =~ /\$Revision:\s+([^\s]+)/; + +################ Program parameters ################ + +### CONFIG +# Some GhostScript programs can produce GIF directly. +# If not, we need the PBM package for the conversion. +my $use_pbm = 1; # GhostScript can not produce GIF +### END CONFIG + +my $res = 82; # default resolution +my $scale = 1; # default scaling +my $mono = 0; # produce BW images if non-zero +my $format; # output format +my $gs_format; # GS output type +my $output; # output, defaults to STDOUT +my $antialias = 4; # antialiasing +my $width; # desired widht +my $height; # desired height + +my ($verbose,$trace,$test,$debug) = (0,0,0,0); +handle_options (); +unless ( defined $format ) { + if ( $0 =~ /2(gif|jpg|png)$/ ) { + set_out_type ($1); + } + else { + set_out_type ('png') unless defined $format; + } +} +print STDERR ("Producing $format ($gs_format) image.\n") if $verbose; + +$trace |= $test | $debug; +$verbose |= $trace; + +################ Presets ################ + +################ The Process ################ + +my $eps_file; +my $err = 0; + +foreach $eps_file ( @ARGV ) { + + unless ( open (EPS, $eps_file) ) { + print STDERR ("Cannot open $eps_file [$!], skipped\n"); + $err++; + next; + } + + my $line = ; + unless ( $line =~ /^%!PS-Adobe.*EPSF-/ ) { + print STDERR ("Not EPS file: $eps_file, skipped\n"); + $err++; + next; + } + + my $ps = ""; # PostScript input data + my $xscale; + my $yscale; + + while ( $line = ) { + + # Search for BoundingBox. + if ( $line =~ /^%%BoundingBox:\s*(\S+)\s+(\S+)\s+(\S+)\s+(\S+)/i ) { + + print STDERR ("$eps_file: x0=$1, y0=$2, w=", $3-$1, ", h=", $4-$2) + if $verbose; + + if ( defined $width ) { + $res = 72; + $xscale = $width / ($3 - $1); + if ( defined $height ) { + $yscale = $height / ($4 - $2); + } + else { + $yscale = $xscale; + $height = ($4 - $2) * $yscale; + } + } + elsif ( defined $height ) { + $res = 72; + $yscale = $height / ($4 - $2); + if ( defined $width ) { + $xscale = $width / ($3 - $1); + } + else { + $xscale = $yscale; + $width = ($3 - $1) * $xscale; + } + } + unless ( defined $xscale ) { + $xscale = $yscale = $scale; + # Calculate actual width. + $width = $3 - $1; + $height = $4 - $2; + # Normal PostScript resolution is 72. + $width *= $res/72 * $xscale; + $height *= $res/72 * $yscale; + # Round up. + $width = int ($width + 0.5) + 1; + $height = int ($height + 0.5) + 1; + } + print STDERR (", width=$width, height=$height\n") if $verbose; + + # Scale. + $ps .= "$xscale $yscale scale\n" + if $xscale != 1 || $yscale != 1; + + # Create PostScript code to translate coordinates. + $ps .= (0-$1) . " " . (0-$2) . " translate\n" + unless $1 == 0 && $2 == 0; + + # Include the image, show and quit. + $ps .= "($eps_file) run\n". + "showpage\n". + "quit\n"; + + last; + } + elsif ( $line =~ /^%%EndComments/i ) { + print STDERR ("No bounding box in $eps_file\n"); + $err++; + last; + } + } + close (EPS); + + my $out_file; # output file + my $pbm_file; # temporary file for PBM conversion + + # Note the temporary PBM file is created where the output file is + # located, since that will guarantee accessibility (and a valid + # filename). + if ( defined $output ) { + $out_file = $output; + $pbm_file = $output.".ppm"; + } + elsif ( $eps_file =~ /^(.+).epsf?$/i ) { + $out_file = "$1.$format"; + $pbm_file = $1.".ppm"; + } + else { + $out_file = $eps_file . ".$format"; + $pbm_file = $eps_file . ".ppm"; + } + print STDERR ("Creating $out_file\n") if $verbose; + + my $gs0 = "gs -q -dNOPAUSE -r$res -g${width}x$height"; + my $gs1 = "-"; + $gs0 .= " -dTextAlphaBits=$antialias -dGraphicsAlphaBits=$antialias" + if $antialias; + if ( $format eq 'png' ) { + mysystem ("$gs0 -sDEVICE=". ($mono ? "pngmono" : $gs_format). + " -sOutputFile=$out_file $gs1", $ps); + } + elsif ( $format eq 'jpg' ) { + mysystem ("$gs0 -sDEVICE=". ($mono ? "jpeggray" : $gs_format). + " -sOutputFile=$out_file $gs1", $ps); + } + elsif ( $format eq 'gif' ) { + if ( $use_pbm ) { + # Convert to PPM and use some of the PBM converters. + mysystem ("$gs0 -sDEVICE=". ($mono ? "pbm" : "ppm"). + " -sOutputFile=$pbm_file $gs1", $ps); + # mysystem ("pnmcrop $pbm_file | ppmtogif > $out_file"); + mysystem ("ppmtogif $pbm_file > $out_file"); + unlink ($pbm_file); + } + else { + # GhostScript has GIF drivers built-in. + mysystem ("$gs0 -sDEVICE=". ($mono ? "gifmono" : "gif8"). + " -sOutputFile=$out_file $gs1", $ps); + } + } + else { + print STDERR ("ASSERT ERROR: Unhandled output type: $format\n"); + exit (1); + } + + unless ( -s $out_file ) { + print STDERR ("Problem creating $out_file for $eps_file\n"); + $err++; + } + +} + +exit 1 if $err; + +################ Subroutines ################ + +sub mysystem { + my ($cmd, $data) = @_; + print STDERR ("+ $cmd\n") if $trace; + if ( $data ) { + if ( $trace ) { + my $dp = ">> " . $data; + $dp =~ s/\n(.)/\n>> $1/g; + print STDERR ("$dp"); + } + open (CMD, "|$cmd") or die ("cmd: $!\n"); + print CMD $data; + close CMD or die ("cmd close: $!\n"); + } + else { + system ($cmd); + } +} + +sub set_out_type { + my ($opt) = lc (shift (@_)); + if ( $opt =~ /^png(mono|gray|16|256|16m)?$/ ) { + $format = 'png'; + $gs_format = $format.(defined $1 ? $1 : '16m'); + } + elsif ( $opt =~ /^gif(mono)?$/ ) { + $format = 'gif'; + $gs_format = $format.(defined $1 ? $1 : ''); + } + elsif ( $opt =~ /^(jpg|jpeg)(gray)?$/ ) { + $format = 'jpg'; + $gs_format = 'jpeg'.(defined $2 ? $2 : ''); + } + else { + print STDERR ("ASSERT ERROR: Invalid value to set_out_type: $opt\n"); + exit (1); + } +} + +sub handle_options { + my ($help) = 0; # handled locally + my ($ident) = 0; # handled locally + + # Process options. + if ( @ARGV > 0 && $ARGV[0] =~ /^[-+]/ ) { + usage () + unless GetOptions ('ident' => \$ident, + 'verbose' => \$verbose, + 'antialias|aa=i' => \$antialias, + 'noantialias|noaa' => sub { $antialias = 0 }, + 'scale=f' => \$scale, + 'width=i' => \$width, + 'height=i' => \$height, + 'output=s' => \$output, + 'png' => \&set_out_type, + 'pngmono' => \&set_out_type, + 'pnggray' => \&set_out_type, + 'png16' => \&set_out_type, + 'png256' => \&set_out_type, + 'png16m' => \&set_out_type, + 'jpg' => \&set_out_type, + 'jpggray' => \&set_out_type, + 'jpeg' => \&set_out_type, + 'jpeggray' => \&set_out_type, + 'gif' => \&set_out_type, + 'gifmono' => \&set_out_type, + 'mono!' => \$mono, + 'resolution=i' => \$res, + 'pbm!' => \$use_pbm, + 'trace' => \$trace, + 'help' => \$help, + 'debug' => \$debug) + && !$help; + } + print STDERR ("This is $my_package [$my_name $my_version]\n") + if $ident; + die ("Only one file argument is allowed when -output is used\n") + if @ARGV > 1 && defined $output; + die ("At least one input file name must be specified\n") + unless @ARGV; + die ("Antialias value must be 0, 1, 2, 4, or 8\n") + unless "$antialias" =~ /^[01248]$/; +} + +sub usage { + print STDERR < (the default), it produces PNG images by +default. Likewise, C defaults to GIF images and C +defaults to JPG. Note that the normal installation procedure will +I install C. + +It uses GhostScript to produce the images. Since modern GhostScript +programs do not support GIF anymore, GIF images are produced via the +Portable PixMap converters (PBM-package). In this case, a temporary +file is created, named after the output file, with the extension +replaced by ".ppm". It is deleted upon completion. + +=head1 ARGUMENTS + +B always requires at least one argument: the name of the EPS +file to be converted. It is possible to specify more than one file +name. This will cause all named files to be converted into separate +files, e.g., "C" will be converted to "C" and +so on. + +=over 4 + +=item B<-png -pngmono -pnggray -png16 -png256 -png16m> + +Each of these options will instruct Ghostscript to use the +corresponding bitmap generator, and supply a C<.png> default +extension for output files. + +=item B<-jpg -jpggray -jpeg -jpeggray> + +Same, but with a C<.jpg> default extension for output files. + +=item B<-gif -gifmono> + +Same, but with a C<.gif> default extension for output files. + +Note: Since modern Ghostscript versions no longer support the GIF +format due to copyright restrictions, B will request +Ghostscript to produce a Portable Bitmap File (.ppm or .pbm) instead +and run the B converter to produce the actual GIF file. + +=item B<-mono> + +This option will select monochrome (BW or gray) output. It forces the +Ghostscript driver to C, C, C, or C. + +=item B<-nomono> + +Produces colour images. This is the default. + +=item B<-width> I + +The desired width of the output image. + +If B<-height> is not specified, the image will be scaled proportionally. + +=item B<-height> I + +The desired height of the output image. + +If B<-width> is not specified, the image will be scaled proportionally. + +=item B<-resolution> I + +Specifies the resolution for the output image. This is the width, in +pixels, of the bitmap image for an EPS image of one inch wide (72 +PostScript points). + +Note that for best results, use the B<-width> and B<-height> options +instead. + +Default value is 82, which causes the converted image to be of more +or less the same size as the EPS image. On my screen, that is. + +=item B<-scale> I + +Specify a scaling factor. This may be a fractional number. + +For a one-inch EPS image, the resultant bitmap image will be +I times I. + +Note that for best results, use the B<-width> and B<-height> options +instead. + +=item B<-antialias> I + +Sets the antialiasing depth. I must be 0 (no antialiasing), 1, 2, +4, or 8. Default value is 4. + +=item B<-noantialias> + +Sets the antialiasing depth to 0. + +=item B<-pbm> + +Forces GIF conversion through the PBM converters. + +=item B<-nopbm> + +Forces GIF conversion through Ghostscript. + +=item B<-output> I + +Stores the output in this file. Only one input file may be supplied if +this option is specified. + +=item B<-help> + +Prints a help message and exits. + +=item B<-ident> + +Prints the program version before doing anything else. + +=item B<-verbose> + +Provides more verbose information. + +=back + +=head1 AUTHOR + +Johan Vromans, . + +=head1 BUGS + +GhostScript and, if required, the PBM package, need to be installed and +accessible through the user's C. + +GhostScript is assumed to be capable of handling all the image types +listed above. + +The EPS should be well-behaving. + +=head1 COPYRIGHT AND DISCLAIMER + +This program is Copyright 1994,2001 by Johan Vromans. +This program is free software; you can redistribute it and/or +modify it under the terms of the Perl Artistic License or the +GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any +later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +If you do not have a copy of the GNU General Public License write to +the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, +MA 02139, USA. + +=cut Property changes on: tags/1.2.7/doc-orig/eps2png ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc-orig/extract-docs =================================================================== --- tags/1.2.7/doc-orig/extract-docs (nonexistent) +++ tags/1.2.7/doc-orig/extract-docs (revision 13657) @@ -0,0 +1,322 @@ +#!/usr/bin/perl +# -*- perl -*- +# +# $Id$ +# +################################################################# +# This script extracts special comments from the source. It assembles +# them in texinfo files that are included in the manual. +################################################################# +# +# The general format of what this script looks for is thusly: +# +# %start-doc category sort-key +# texi stuff goes here +# %end-doc +# +# The lines with the %start-doc and %end-doc are not included in the +# texi extraction; only the lines between them. The category is used +# to determine the file that's created; a category of "foo" causes a +# file "foo.texi" to be created. The sort-keys are case insensitive. +# The text extracted is sorte according to the key and put into the +# file according to the category. Each unique sort-key causes a @node +# to be created, unless that sort-key's text already has a @node in +# it. +# If the sort-key contains space characters, it should be enclosed by +# quotation marks ("). Leading digits in the sort key optionally followed +# by space are removed after sort but before creation of nodes. This +# allows to manipulate the order of nodes in the manual. +# +# Note that we synthesize a special @syntax command, which should be +# used for all things syntax. We change those to whatever the current +# desired style is for syntaxes (currently, a cartouche box of +# non-wrapped but variable-pitch font). +# +# For extracting actions, this script expects a very specific syntax +# to be used. It looks like this, with one or more lines +# (continuations are like this example): +# +# static const char some_string_help[] = +# "some text\n" +# "some text"; +# +# Repeat for some_string_syntax[], then follow those with the usual +# %start-doc. Note that the %start-doc for actions must use the +# category "actions" and the sort key must match the action name. +# +# Within start-doc/end-doc pairs, you can use two special @-lines +# to control the generated node names and document structure. +# +# @nodetype section +# You can specify section, subsection, unnumberedsubsec, etc. Each +# unique sort key within each category is assigned one of these. +# @nodename pattern +# A sprintf-like pattern to use to modify the sort-key to make a +# node name. Since node names must be unique and have various +# restrictions as to what characters you can use in them, this +# allows you to use a pattern for various categories which will help +# keep node names unique without requiring lots of repetetive typing +# in the source files. + +$docdir = shift; +$docdir = "." unless $docdir; +$srcdir = "$docdir/../src"; +$docdir = "."; + +my $debug = 0; + +open(FIND, "find $srcdir -type f -name '*.[chly]' -print | sort |"); +while () { + s/[\r\n]+$//; + &scan_file($_); +} +close (FIND); + +sub dsort { + my ($a, $b) = @_; + $a =~ tr/A-Z/a-z/; + $b =~ tr/A-Z/a-z/; + return $a cmp $b; +} + +for $cat (sort keys %text) { + print "$cat\n"; + @k = sort {&dsort($a,$b)} keys %{$text{$cat}}; + $new = ''; + $new .= "\@c key $cat\n"; + if ($cat eq "actions") { + &dump_00_keys($cat, "\0\$"); + $new .= "\n\@menu\n"; + for $hid (sort keys %{$hids{$cat}}) { + if ($hid =~ /../) { + $new .= "* ${hid} actions::\n"; + } else { + $new .= "* core actions::\n"; + } + } + $new .= "\@end menu\n\n"; + for $hid (sort keys %{$hids{$cat}}) { + if ($hid =~ /../) { + $new .= "\@node $hid actions\n"; + $new .= "\@section $hid actions\n"; + &dump_00_keys($cat, "\0$hid\$"); + } else { + $new .= "\@node core actions\n"; + $new .= "\@section Core actions\n"; + } + $new .= "\@menu\n"; + for $key (@k) { + next unless $key =~ /\0$hid$/; + next if $key =~ /^00/; + $k2 = $title{$cat}{$key}; + if ($hid =~ /\S/ && $hid !~ /common/) { + $k2 = "$hid $k2"; + } + $new .= "* ${k2} Action:: $desc{$key}\n"; + } + $new .= "\@end menu\n"; + for $key (@k) { + next unless $key =~ /\0$hid$/; + next if $key =~ /^00/; + $k2 = $title{$cat}{$key}; + if ($hid =~ /\S/ && $hid !~ /common/) { + $k2 = "$hid $k2"; + } + if ($key !~ /^00/) { + $new .= "\@node $k2 Action\n"; + $new .= "\@subsection $k2\n"; + } + $new .= "\@c key $k2 in hid $hid\n"; + if ($synt{$key}) { + $new .= "\@cartouche\n\@format\n"; + $new .= $synt{$key}; + $new .= "\@end format\n\@end cartouche\n\n"; + } + if ($desc{$key}) { + $new .= $desc{$key} . "\n"; + } + $new .= $text{$cat}{$key}; + if (! $desc{$key} && ! $text{$cat}{$key} ) { + $new .= "No documentation yet.\n"; + } + $new .= "\n"; + } + } + } else { + $nodetype = "section"; + &dump_00_keys($cat, ""); + $new .= "\@menu\n"; + $nodename = "%s"; + for $key (@k) { + if ($nodename{$cat}{$key}) { + $nodename = $nodename{$cat}{$key}; + } + next if $key =~ /^00/; + $k2 = $title{$cat}{$key}; + # strip leading digits from the key string + $k2 =~ s/\A\d+\s*//g; + $k2 = sprintf($nodename, $k2); + if ($text{$cat}{$key} !~ /\@node/) { + $new .="* ${k2}::\n"; + } + } + $new .= "\@end menu\n"; + $nodename = "%s"; + for $key (@k) { + if ($nodetype{$cat}{$key}) { + $nodetype = $nodetype{$cat}{$key}; + } + if ($nodename{$cat}{$key}) { + $nodename = $nodename{$cat}{$key}; + } + next if $key =~ /^00/; + $k2 = $title{$cat}{$key}; + # strip leading digits from the key string + $k2 =~ s/\A\d+\s*//g; + $k2n = sprintf($nodename, $k2); + $new .= "\@c $cat $k2\n"; + if ($text{$cat}{$key} !~ /\@node/) { + $new .= "\@node $k2n\n"; + $new .= "\@$nodetype $k2\n"; + } + $new .= $text{$cat}{$key}; + } + } + $^A = ""; + $line = join(' ', @k); + formline(" ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ~~\n", $line); + print $^A; + + $old = ''; + if ( -f "$docdir/$cat.texi") { + open(CAT, "$docdir/$cat.texi"); + $old = join('', ); + close CAT; + } + if ($old ne $new) { + open(CAT, ">$docdir/$cat.texi"); + print CAT $new; + close CAT; + } +} + +sub dump_00_keys { + my($cat, $regex) = @_; + for $k (@k) { + next unless $k =~ /00.*$regex/; + $new .= $text{$cat}{$k}; + } +} + +sub scan_file { + my ($name) = @_; + print "DEBUG: sub_scan($name)\n" if ($debug); + + # if the source file was in $(srcdir)/hid// then + # pick out the name of the hid and put it into $srcdir. + if ($name =~ m@hid/([^/]+)/@) { + $hid = "$1"; + } else { + $hid = ""; + } + $lineno = 0; + + # skip processing of lex/yacc output files + if ($name =~ /\.[ch]$/) { + $new = $name; + $new =~ s/\.[ch]$/\.y/; + return if -f $new; + $new =~ s/\.y$/\.l/; + return if -f $new; + } + + open(F, $name); + while () { + $lineno ++; + if (/^static\s+const\s+char\s+.*_(help|syntax)\[\]\s*=(.*)/) { + $tag = $1; + $last = 0; + $pending{$tag} = ''; + + # note that the help/syntax string may start on the same line + # as the "static const char"... bit so we pick out that part and + # process it first. + $_ = $2; + LOOP: { + do { + # eat trailing whitespace, new-lines, and carriage returns + s/[\r\n\s]+$//; + + # we're done if we found the terminating ";" + $last = 1 if /;$/; + + # otherwise we need to eat leading whitespace and the leading quote + s/^[\s]*\"//; #" + + # convert \n to a newline + s/\\n/\n/g; + + # eat trailing quotes + s/\";?$//; #" + s/\\\"/\"/g; #" + s/ "/``/g; + s/" /''/g; + $pending{$tag} .= $_; + last if $last; + } while (); + } + # spit out a warning in case we have a malformed help + if ($pending{$tag} =~ /%(start|end)-doc/) { + print "WARNING: $name line $lineno has a $1 string that includes a %start-doc or %end-doc\n"; + print " tag:\n$pending{$tag}\n\n"; + } + next; + } + + if (/%start-doc\s+(\S+)\s+([^"^\s]+|".*?")(\s+(.*))?/) { + # pattern to look for: + # start-doc -> "%start-doc" + # \s+ -> one ore more whitespace + # (\S+) -> string with no whitespace, goes to $1 + # \s+ -> one ore more whitespace + # ([^"^\s]+|".*?") -> a space-less string, or a string delimited by ", goes to $2 + # (\s+(.*))? -> zero or more space separated strings + + $cat = $1; + $key = $2; + # strip leading and trailing quotation marks from the key string + $key =~ s/\A"//g; + $key =~ s/"\Z//g; + $title = $4; + if ($title) { + $title{$cat}{"$key\0$hid"} = $title; + } else { + $title{$cat}{"$key\0$hid"} = $key; + } + $text{$cat}{"$key\0$hid"} .= "\@c $name $lineno\n"; + $hids{$cat}{$hid} = 1; + if ($cat =~ /^(.*_)?actions/) { + $desc{"$key\0$hid"} = $pending{'help'}; + $synt{"$key\0$hid"} = $pending{'syntax'}; + %pending = (); + } + while () { + next if /^\*\/$/; + next if /^\/\*$/; + last if /%end-doc/; + s/\@syntax/\@cartouche\n\@format/g; + s/\@end syntax/\@end format\n\@end cartouche/g; + if (/^\@nodetype\s*(\S+)/) { + $nodetype{$cat}{"$key\0$hid"} = $1; + next; + } + if (/^\@nodename\s*(.+)/) { + $nodename{$cat}{"$key\0$hid"} = $1; + next; + } + $text{$cat}{"$key\0$hid"} .= $_; + } + } + } + close (F); +} Property changes on: tags/1.2.7/doc-orig/extract-docs ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode.pcb =================================================================== --- tags/1.2.7/doc-orig/gcode.pcb (nonexistent) +++ tags/1.2.7/doc-orig/gcode.pcb (revision 13657) @@ -0,0 +1,1000 @@ +# release: pcb 20091103 +# date: Tue Feb 9 17:50:10 2010 +# user: amc (amc,/home/alberto,S-1-5-21-3544562028-792812758-4257637587-9314) +# host: ni28979b.office.amsiag.com + +# To read pcb files, the pcb version (or the cvs source date) must be >= the file version +FileVersion[20070407] + +PCB["" 280000 160000] + +Grid[1000.000000 0 0 0] +Cursor[0 0 0.000000] +PolyArea[200000000.000000] +Thermal[0.500000] +DRC[1000 1000 1000 1000 1500 1000] +Flags("showdrc,nameonpcb,swapstartdir,clearnew,snappin") +Groups("1,c:2,s:3:4:5:6:7:8") +Styles["Signal,4000,8000,3000,2000:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600"] + +Symbol(' ' 18) +( +) +Symbol('!' 12) +( + SymbolLine(0 45 0 50 8) + SymbolLine(0 10 0 35 8) +) +Symbol('"' 12) +( + SymbolLine(0 10 0 20 8) + SymbolLine(10 10 10 20 8) +) +Symbol('#' 12) +( + SymbolLine(0 35 20 35 8) + SymbolLine(0 25 20 25 8) + SymbolLine(15 20 15 40 8) + SymbolLine(5 20 5 40 8) +) +Symbol('$' 12) +( + SymbolLine(15 15 20 20 8) + SymbolLine(5 15 15 15 8) + SymbolLine(0 20 5 15 8) + SymbolLine(0 20 0 25 8) + SymbolLine(0 25 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 40 8) + SymbolLine(15 45 20 40 8) + SymbolLine(5 45 15 45 8) + SymbolLine(0 40 5 45 8) + SymbolLine(10 10 10 50 8) +) +Symbol('%' 12) +( + SymbolLine(0 15 0 20 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 10 10 8) + SymbolLine(10 10 15 15 8) + SymbolLine(15 15 15 20 8) + SymbolLine(10 25 15 20 8) + SymbolLine(5 25 10 25 8) + SymbolLine(0 20 5 25 8) + SymbolLine(0 50 40 10 8) + SymbolLine(35 50 40 45 8) + SymbolLine(40 40 40 45 8) + SymbolLine(35 35 40 40 8) + SymbolLine(30 35 35 35 8) + SymbolLine(25 40 30 35 8) + SymbolLine(25 40 25 45 8) + SymbolLine(25 45 30 50 8) + SymbolLine(30 50 35 50 8) +) +Symbol('&' 12) +( + SymbolLine(0 45 5 50 8) + SymbolLine(0 15 0 25 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 35 15 20 8) + SymbolLine(5 50 10 50 8) + SymbolLine(10 50 20 40 8) + SymbolLine(0 25 25 50 8) + SymbolLine(5 10 10 10 8) + SymbolLine(10 10 15 15 8) + SymbolLine(15 15 15 20 8) + SymbolLine(0 35 0 45 8) +) +Symbol(''' 12) +( + SymbolLine(0 20 10 10 8) +) +Symbol('(' 12) +( + SymbolLine(0 45 5 50 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 15 0 45 8) +) +Symbol(')' 12) +( + SymbolLine(0 10 5 15 8) + SymbolLine(5 15 5 45 8) + SymbolLine(0 50 5 45 8) +) +Symbol('*' 12) +( + SymbolLine(0 20 20 40 8) + SymbolLine(0 40 20 20 8) + SymbolLine(0 30 20 30 8) + SymbolLine(10 20 10 40 8) +) +Symbol('+' 12) +( + SymbolLine(0 30 20 30 8) + SymbolLine(10 20 10 40 8) +) +Symbol(',' 12) +( + SymbolLine(0 60 10 50 8) +) +Symbol('-' 12) +( + SymbolLine(0 30 20 30 8) +) +Symbol('.' 12) +( + SymbolLine(0 50 5 50 8) +) +Symbol('/' 12) +( + SymbolLine(0 45 30 15 8) +) +Symbol('0' 12) +( + SymbolLine(0 45 5 50 8) + SymbolLine(0 15 0 45 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 40 20 20 8) +) +Symbol('1' 12) +( + SymbolLine(5 50 15 50 8) + SymbolLine(10 10 10 50 8) + SymbolLine(0 20 10 10 8) +) +Symbol('2' 12) +( + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 20 10 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 25 8) + SymbolLine(0 50 25 25 8) + SymbolLine(0 50 25 50 8) +) +Symbol('3' 12) +( + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 30 20 30 8) +) +Symbol('4' 12) +( + SymbolLine(0 30 20 10 8) + SymbolLine(0 30 25 30 8) + SymbolLine(20 10 20 50 8) +) +Symbol('5' 12) +( + SymbolLine(0 10 20 10 8) + SymbolLine(0 10 0 30 8) + SymbolLine(0 30 5 25 8) + SymbolLine(5 25 15 25 8) + SymbolLine(15 25 20 30 8) + SymbolLine(20 30 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) +) +Symbol('6' 12) +( + SymbolLine(15 10 20 15 8) + SymbolLine(5 10 15 10 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 15 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(15 30 20 35 8) + SymbolLine(0 30 15 30 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(20 35 20 45 8) +) +Symbol('7' 12) +( + SymbolLine(0 50 25 25 8) + SymbolLine(25 10 25 25 8) + SymbolLine(0 10 25 10 8) +) +Symbol('8' 12) +( + SymbolLine(0 45 5 50 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 25 5 30 8) + SymbolLine(0 15 0 25 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 25 8) + SymbolLine(15 30 20 25 8) +) +Symbol('9' 12) +( + SymbolLine(0 50 20 30 8) + SymbolLine(20 15 20 30 8) + SymbolLine(15 10 20 15 8) + SymbolLine(5 10 15 10 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 15 0 25 8) + SymbolLine(0 25 5 30 8) + SymbolLine(5 30 20 30 8) +) +Symbol(':' 12) +( + SymbolLine(0 25 5 25 8) + SymbolLine(0 35 5 35 8) +) +Symbol(';' 12) +( + SymbolLine(0 50 10 40 8) + SymbolLine(10 25 10 30 8) +) +Symbol('<' 12) +( + SymbolLine(0 30 10 20 8) + SymbolLine(0 30 10 40 8) +) +Symbol('=' 12) +( + SymbolLine(0 25 20 25 8) + SymbolLine(0 35 20 35 8) +) +Symbol('>' 12) +( + SymbolLine(0 20 10 30 8) + SymbolLine(0 40 10 30 8) +) +Symbol('?' 12) +( + SymbolLine(10 30 10 35 8) + SymbolLine(10 45 10 50 8) + SymbolLine(0 15 0 20 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 20 8) + SymbolLine(10 30 20 20 8) +) +Symbol('@' 12) +( + SymbolLine(0 10 0 40 8) + SymbolLine(0 40 10 50 8) + SymbolLine(10 50 40 50 8) + SymbolLine(50 35 50 10 8) + SymbolLine(50 10 40 0 8) + SymbolLine(40 0 10 0 8) + SymbolLine(10 0 0 10 8) + SymbolLine(15 20 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 30 35 8) + SymbolLine(30 35 35 30 8) + SymbolLine(35 30 40 35 8) + SymbolLine(35 30 35 15 8) + SymbolLine(35 20 30 15 8) + SymbolLine(20 15 30 15 8) + SymbolLine(20 15 15 20 8) + SymbolLine(40 35 50 35 8) +) +Symbol('A' 12) +( + SymbolLine(0 15 0 50 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 20 10 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 50 8) + SymbolLine(0 30 25 30 8) +) +Symbol('B' 12) +( + SymbolLine(0 50 20 50 8) + SymbolLine(20 50 25 45 8) + SymbolLine(25 35 25 45 8) + SymbolLine(20 30 25 35 8) + SymbolLine(5 30 20 30 8) + SymbolLine(5 10 5 50 8) + SymbolLine(0 10 20 10 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 25 8) + SymbolLine(20 30 25 25 8) +) +Symbol('C' 12) +( + SymbolLine(5 50 20 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(0 15 0 45 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 20 10 8) +) +Symbol('D' 12) +( + SymbolLine(5 10 5 50 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 45 8) + SymbolLine(20 50 25 45 8) + SymbolLine(0 50 20 50 8) + SymbolLine(0 10 20 10 8) +) +Symbol('E' 12) +( + SymbolLine(0 30 15 30 8) + SymbolLine(0 50 20 50 8) + SymbolLine(0 10 0 50 8) + SymbolLine(0 10 20 10 8) +) +Symbol('F' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 10 20 10 8) + SymbolLine(0 30 15 30 8) +) +Symbol('G' 12) +( + SymbolLine(20 10 25 15 8) + SymbolLine(5 10 20 10 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 15 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 20 50 8) + SymbolLine(20 50 25 45 8) + SymbolLine(25 35 25 45 8) + SymbolLine(20 30 25 35 8) + SymbolLine(10 30 20 30 8) +) +Symbol('H' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(25 10 25 50 8) + SymbolLine(0 30 25 30 8) +) +Symbol('I' 12) +( + SymbolLine(0 10 10 10 8) + SymbolLine(5 10 5 50 8) + SymbolLine(0 50 10 50 8) +) +Symbol('J' 12) +( + SymbolLine(0 10 15 10 8) + SymbolLine(15 10 15 45 8) + SymbolLine(10 50 15 45 8) + SymbolLine(5 50 10 50 8) + SymbolLine(0 45 5 50 8) +) +Symbol('K' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 30 20 10 8) + SymbolLine(0 30 20 50 8) +) +Symbol('L' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 50 20 50 8) +) +Symbol('M' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 10 15 25 8) + SymbolLine(15 25 30 10 8) + SymbolLine(30 10 30 50 8) +) +Symbol('N' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 10 0 15 8) + SymbolLine(0 15 25 40 8) + SymbolLine(25 10 25 50 8) +) +Symbol('O' 12) +( + SymbolLine(0 15 0 45 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) +) +Symbol('P' 12) +( + SymbolLine(5 10 5 50 8) + SymbolLine(0 10 20 10 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 25 8) + SymbolLine(20 30 25 25 8) + SymbolLine(5 30 20 30 8) +) +Symbol('Q' 12) +( + SymbolLine(0 15 0 45 8) + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 15 10 8) + SymbolLine(15 10 20 15 8) + SymbolLine(20 15 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(10 40 20 50 8) +) +Symbol('R' 12) +( + SymbolLine(0 10 20 10 8) + SymbolLine(20 10 25 15 8) + SymbolLine(25 15 25 25 8) + SymbolLine(20 30 25 25 8) + SymbolLine(5 30 20 30 8) + SymbolLine(5 10 5 50 8) + SymbolLine(5 30 25 50 8) +) +Symbol('S' 12) +( + SymbolLine(20 10 25 15 8) + SymbolLine(5 10 20 10 8) + SymbolLine(0 15 5 10 8) + SymbolLine(0 15 0 25 8) + SymbolLine(0 25 5 30 8) + SymbolLine(5 30 20 30 8) + SymbolLine(20 30 25 35 8) + SymbolLine(25 35 25 45 8) + SymbolLine(20 50 25 45 8) + SymbolLine(5 50 20 50 8) + SymbolLine(0 45 5 50 8) +) +Symbol('T' 12) +( + SymbolLine(0 10 20 10 8) + SymbolLine(10 10 10 50 8) +) +Symbol('U' 12) +( + SymbolLine(0 10 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(20 10 20 45 8) +) +Symbol('V' 12) +( + SymbolLine(0 10 0 40 8) + SymbolLine(0 40 10 50 8) + SymbolLine(10 50 20 40 8) + SymbolLine(20 10 20 40 8) +) +Symbol('W' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 50 15 35 8) + SymbolLine(15 35 30 50 8) + SymbolLine(30 10 30 50 8) +) +Symbol('X' 12) +( + SymbolLine(0 10 0 15 8) + SymbolLine(0 15 25 40 8) + SymbolLine(25 40 25 50 8) + SymbolLine(0 40 0 50 8) + SymbolLine(0 40 25 15 8) + SymbolLine(25 10 25 15 8) +) +Symbol('Y' 12) +( + SymbolLine(0 10 0 15 8) + SymbolLine(0 15 10 25 8) + SymbolLine(10 25 20 15 8) + SymbolLine(20 10 20 15 8) + SymbolLine(10 25 10 50 8) +) +Symbol('Z' 12) +( + SymbolLine(0 10 25 10 8) + SymbolLine(25 10 25 15 8) + SymbolLine(0 40 25 15 8) + SymbolLine(0 40 0 50 8) + SymbolLine(0 50 25 50 8) +) +Symbol('[' 12) +( + SymbolLine(0 10 5 10 8) + SymbolLine(0 10 0 50 8) + SymbolLine(0 50 5 50 8) +) +Symbol('\' 12) +( + SymbolLine(0 15 30 45 8) +) +Symbol(']' 12) +( + SymbolLine(0 10 5 10 8) + SymbolLine(5 10 5 50 8) + SymbolLine(0 50 5 50 8) +) +Symbol('^' 12) +( + SymbolLine(0 15 5 10 8) + SymbolLine(5 10 10 15 8) +) +Symbol('_' 12) +( + SymbolLine(0 50 20 50 8) +) +Symbol('a' 12) +( + SymbolLine(15 30 20 35 8) + SymbolLine(5 30 15 30 8) + SymbolLine(0 35 5 30 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(20 30 20 45 8) + SymbolLine(20 45 25 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) +) +Symbol('b' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(20 35 20 45 8) + SymbolLine(15 30 20 35 8) + SymbolLine(5 30 15 30 8) + SymbolLine(0 35 5 30 8) +) +Symbol('c' 12) +( + SymbolLine(5 30 20 30 8) + SymbolLine(0 35 5 30 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 20 50 8) +) +Symbol('d' 12) +( + SymbolLine(20 10 20 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) +) +Symbol('e' 12) +( + SymbolLine(5 50 20 50 8) + SymbolLine(0 45 5 50 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(0 40 20 40 8) + SymbolLine(20 40 20 35 8) +) +Symbol('f' 10) +( + SymbolLine(5 15 5 50 8) + SymbolLine(5 15 10 10 8) + SymbolLine(10 10 15 10 8) + SymbolLine(0 30 10 30 8) +) +Symbol('g' 12) +( + SymbolLine(15 30 20 35 8) + SymbolLine(5 30 15 30 8) + SymbolLine(0 35 5 30 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(0 60 5 65 8) + SymbolLine(5 65 15 65 8) + SymbolLine(15 65 20 60 8) + SymbolLine(20 30 20 60 8) +) +Symbol('h' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 50 8) +) +Symbol('i' 10) +( + SymbolLine(0 20 0 25 8) + SymbolLine(0 35 0 50 8) +) +Symbol('j' 10) +( + SymbolLine(5 20 5 25 8) + SymbolLine(5 35 5 60 8) + SymbolLine(0 65 5 60 8) +) +Symbol('k' 12) +( + SymbolLine(0 10 0 50 8) + SymbolLine(0 35 15 50 8) + SymbolLine(0 35 10 25 8) +) +Symbol('l' 10) +( + SymbolLine(0 10 0 45 8) + SymbolLine(0 45 5 50 8) +) +Symbol('m' 12) +( + SymbolLine(5 35 5 50 8) + SymbolLine(5 35 10 30 8) + SymbolLine(10 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 50 8) + SymbolLine(20 35 25 30 8) + SymbolLine(25 30 30 30 8) + SymbolLine(30 30 35 35 8) + SymbolLine(35 35 35 50 8) + SymbolLine(0 30 5 35 8) +) +Symbol('n' 12) +( + SymbolLine(5 35 5 50 8) + SymbolLine(5 35 10 30 8) + SymbolLine(10 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 50 8) + SymbolLine(0 30 5 35 8) +) +Symbol('o' 12) +( + SymbolLine(0 35 0 45 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 15 30 8) + SymbolLine(15 30 20 35 8) + SymbolLine(20 35 20 45 8) + SymbolLine(15 50 20 45 8) + SymbolLine(5 50 15 50 8) + SymbolLine(0 45 5 50 8) +) +Symbol('p' 12) +( + SymbolLine(5 35 5 65 8) + SymbolLine(0 30 5 35 8) + SymbolLine(5 35 10 30 8) + SymbolLine(10 30 20 30 8) + SymbolLine(20 30 25 35 8) + SymbolLine(25 35 25 45 8) + SymbolLine(20 50 25 45 8) + SymbolLine(10 50 20 50 8) + SymbolLine(5 45 10 50 8) +) +Symbol('q' 12) +( + SymbolLine(20 35 20 65 8) + SymbolLine(15 30 20 35 8) + SymbolLine(5 30 15 30 8) + SymbolLine(0 35 5 30 8) + SymbolLine(0 35 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) +) +Symbol('r' 12) +( + SymbolLine(5 35 5 50 8) + SymbolLine(5 35 10 30 8) + SymbolLine(10 30 20 30 8) + SymbolLine(0 30 5 35 8) +) +Symbol('s' 12) +( + SymbolLine(5 50 20 50 8) + SymbolLine(20 50 25 45 8) + SymbolLine(20 40 25 45 8) + SymbolLine(5 40 20 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 20 30 8) + SymbolLine(20 30 25 35 8) + SymbolLine(0 45 5 50 8) +) +Symbol('t' 10) +( + SymbolLine(5 10 5 45 8) + SymbolLine(5 45 10 50 8) + SymbolLine(0 25 10 25 8) +) +Symbol('u' 12) +( + SymbolLine(0 30 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) + SymbolLine(20 30 20 45 8) +) +Symbol('v' 12) +( + SymbolLine(0 30 0 40 8) + SymbolLine(0 40 10 50 8) + SymbolLine(10 50 20 40 8) + SymbolLine(20 30 20 40 8) +) +Symbol('w' 12) +( + SymbolLine(0 30 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(5 50 10 50 8) + SymbolLine(10 50 15 45 8) + SymbolLine(15 30 15 45 8) + SymbolLine(15 45 20 50 8) + SymbolLine(20 50 25 50 8) + SymbolLine(25 50 30 45 8) + SymbolLine(30 30 30 45 8) +) +Symbol('x' 12) +( + SymbolLine(0 30 20 50 8) + SymbolLine(0 50 20 30 8) +) +Symbol('y' 12) +( + SymbolLine(0 30 0 45 8) + SymbolLine(0 45 5 50 8) + SymbolLine(20 30 20 60 8) + SymbolLine(15 65 20 60 8) + SymbolLine(5 65 15 65 8) + SymbolLine(0 60 5 65 8) + SymbolLine(5 50 15 50 8) + SymbolLine(15 50 20 45 8) +) +Symbol('z' 12) +( + SymbolLine(0 30 20 30 8) + SymbolLine(0 50 20 30 8) + SymbolLine(0 50 20 50 8) +) +Symbol('{' 12) +( + SymbolLine(5 15 10 10 8) + SymbolLine(5 15 5 25 8) + SymbolLine(0 30 5 25 8) + SymbolLine(0 30 5 35 8) + SymbolLine(5 35 5 45 8) + SymbolLine(5 45 10 50 8) +) +Symbol('|' 12) +( + SymbolLine(0 10 0 50 8) +) +Symbol('}' 12) +( + SymbolLine(0 10 5 15 8) + SymbolLine(5 15 5 25 8) + SymbolLine(5 25 10 30 8) + SymbolLine(5 35 10 30 8) + SymbolLine(5 35 5 45 8) + SymbolLine(0 50 5 45 8) +) +Symbol('~' 12) +( + SymbolLine(0 35 5 30 8) + SymbolLine(5 30 10 30 8) + SymbolLine(10 30 15 35 8) + SymbolLine(15 35 20 35 8) + SymbolLine(20 35 25 30 8) +) +Via[48000 28000 8000 4000 0 3000 "" ""] +Via[63000 86000 8000 4000 0 3000 "" ""] + +Element["" "DIP18" "U5" "16F84" 116500 28500 17000 5000 3 100 ""] +( + Pin[0 0 8000 3000 5600 2800 "1" "1" "square"] + Pin[0 10000 8000 3000 5600 2800 "2" "2" ""] + Pin[0 20000 8000 3000 5600 2800 "3" "3" ""] + Pin[0 30000 8000 3000 5600 2800 "4" "4" ""] + Pin[0 40000 8000 3000 5600 2800 "5" "5" ""] + Pin[0 50000 8000 3000 5600 2800 "6" "6" ""] + Pin[0 60000 8000 3000 5600 2800 "7" "7" ""] + Pin[0 70000 8000 3000 5600 2800 "8" "8" ""] + Pin[0 80000 8000 3000 5600 2800 "9" "9" ""] + Pin[30000 80000 8000 3000 5600 2800 "10" "10" ""] + Pin[30000 70000 8000 3000 5600 2800 "11" "11" ""] + Pin[30000 60000 8000 3000 5600 2800 "12" "12" ""] + Pin[30000 50000 8000 3000 5600 2800 "13" "13" ""] + Pin[30000 40000 8000 3000 5600 2800 "14" "14" ""] + Pin[30000 30000 8000 3000 5600 2800 "15" "15" ""] + Pin[30000 20000 8000 3000 5600 2800 "16" "16" ""] + Pin[30000 10000 8000 3000 5600 2800 "17" "17" ""] + Pin[30000 0 8000 3000 5600 2800 "18" "18" ""] + ElementLine [20000 -5000 35000 -5000 1000] + ElementLine [-5000 -5000 10000 -5000 1000] + ElementLine [35000 85000 35000 -5000 1000] + ElementLine [-5000 85000 35000 85000 1000] + ElementLine [-5000 -5000 -5000 85000 1000] + ElementArc [15000 -5000 5000 5000 0 180 1000] + + ) + +Element["" "TO220" "U6" "unknown" 179500 45000 23000 -15000 0 100 ""] +( + Pin[0 -10000 8000 3000 8600 5000 "1" "1" "square,edge2"] + Pin[0 0 8000 3000 8600 5000 "2" "2" "edge2"] + Pin[0 10000 8000 3000 8600 5000 "3" "3" "edge2"] + Pin[67000 0 17500 3000 15100 13000 "4" "4" "edge2"] + ElementLine [0 -10000 18000 -10000 3000] + ElementLine [0 0 18000 0 3000] + ElementLine [0 10000 18000 10000 3000] + ElementLine [18000 -20000 18000 20000 2000] + ElementLine [18000 20000 55500 20000 2000] + ElementLine [55500 -20000 55500 20000 2000] + ElementLine [18000 -20000 55500 -20000 2000] + ElementLine [55500 -20000 55500 20000 2000] + ElementLine [55500 20000 68000 20000 2000] + ElementLine [68000 18500 68000 20000 2000] + ElementLine [68000 18500 75000 18500 2000] + ElementLine [75000 18500 75000 20000 2000] + ElementLine [75000 20000 79000 20000 2000] + ElementLine [79000 -20000 79000 20000 2000] + ElementLine [75000 -20000 79000 -20000 2000] + ElementLine [75000 -20000 75000 -18500 2000] + ElementLine [68000 -18500 75000 -18500 2000] + ElementLine [68000 -20000 68000 -18500 2000] + ElementLine [55500 -20000 68000 -20000 2000] + + ) + +Element["" "RCY300" "C11" "unknown" 205500 94500 2500 10000 3 100 ""] +( + Pin[0 0 8000 3000 5600 5000 "1" "1" ""] + Pin[0 30000 8000 3000 5600 5000 "2" "2" "square"] + ElementArc [0 15000 30000 30000 270 360 1000] + + ) + +Element["" "ALF400" "Z5" "unknown" 129000 142500 -33800 900 0 100 ""] +( + Pin[0 0 8000 3000 4600 2000 "2" "2" "square,edge2"] + Pin[-40000 0 8000 3000 4600 2000 "1" "1" "edge2"] + ElementLine [-13300 0 0 0 1000] + ElementLine [-40000 0 -26700 0 1000] + ElementLine [-13300 0 -26700 6600 1000] + ElementLine [-26700 -6600 -26700 6600 1000] + ElementLine [-26700 -6600 -13300 0 1000] + ElementLine [-13300 -6600 -13300 6600 1000] + + ) + +Element["" "ACY400" "R21" "unknown" 82500 28000 -5300 32000 3 100 ""] +( + Pin[0 0 8000 3000 5100 3000 "1" "1" "square"] + Pin[0 40000 8000 3000 5100 3000 "2" "2" ""] + ElementLine [0 0 0 10000 1000] + ElementLine [0 30000 0 40000 1000] + ElementLine [3300 10000 3300 30000 1000] + ElementLine [-3300 30000 3300 30000 1000] + ElementLine [-3300 10000 -3300 30000 1000] + ElementLine [-3300 10000 3300 10000 1000] + + ) + +Element["" "AXIAL_LAY-200" "C13" "100n" 87000 110000 -6000 -11400 0 100 ""] +( + Pin[5000 0 8000 3000 8600 3000 "1" "1" "edge2"] + Pin[-15000 0 8000 3000 8600 3000 "2" "2" "edge2"] + ElementLine [0 -1600 0 1600 1000] + ElementLine [-10000 -1600 0 -1600 1000] + ElementLine [-10000 -1600 -10000 1600 1000] + ElementLine [-10000 1600 0 1600 1000] + ElementLine [-15000 0 -10000 0 1000] + ElementLine [0 0 5000 0 1000] + + ) +Layer(1 "component") +( +) +Layer(2 "solder") +( + Line[48000 28000 48000 30000 4000 4000 "clearline"] + Line[48000 30000 69000 51000 4000 4000 "clearline"] + Line[69000 51000 96000 51000 4000 4000 "clearline"] + Line[96000 51000 98000 53000 4000 4000 "clearline"] + Line[98000 53000 98000 60000 4000 4000 "clearline"] + Line[98000 60000 106000 68000 4000 4000 "clearline"] + Line[106000 68000 116000 68000 4000 4000 "clearline"] + Line[116000 68000 116500 68500 4000 4000 "clearline"] + Line[82500 68000 82500 99500 4000 4000 "clearline"] + Line[82500 99500 72000 110000 4000 4000 "clearline"] + Line[92000 110000 93000 110000 4000 4000 "clearline"] + Line[93000 110000 101000 102000 4000 4000 "clearline"] + Line[101000 102000 101000 81000 4000 4000 "clearline"] + Line[101000 81000 103000 79000 4000 4000 "clearline"] + Line[103000 79000 116000 79000 4000 4000 "clearline"] + Line[116000 79000 116500 78500 4000 4000 "clearline"] + Line[116500 48500 129500 48500 4000 4000 "clearline"] + Line[129500 48500 133000 52000 4000 4000 "clearline"] + Line[133000 52000 133000 64000 4000 4000 "clearline"] + Line[133000 64000 137000 68000 4000 4000 "clearline"] + Line[137000 68000 146000 68000 4000 4000 "clearline"] + Line[146000 68000 146500 68500 4000 4000 "clearline"] + Line[146500 88500 137500 88500 4000 4000 "clearline"] + Line[137500 88500 129000 97000 4000 4000 "clearline"] + Line[129000 97000 118000 97000 4000 4000 "clearline"] + Line[118000 97000 116500 98500 4000 4000 "clearline"] + Line[129000 142500 131500 142500 4000 4000 "clearline"] + Line[131500 142500 161000 113000 4000 4000 "clearline"] + Line[161000 113000 161000 63000 4000 4000 "clearline"] + Line[161000 63000 158000 60000 4000 4000 "clearline"] + Line[158000 60000 148000 60000 4000 4000 "clearline"] + Line[148000 60000 146500 58500 4000 4000 "clearline"] + Line[205500 94500 205500 44500 4000 4000 "clearline"] + Line[205500 44500 197000 36000 4000 4000 "clearline"] + Line[197000 36000 180500 36000 4000 4000 "clearline"] + Line[180500 36000 179500 35000 4000 4000 "clearline"] + Line[82500 28000 96500 14000 4000 4000 "clearline"] + Line[96500 14000 128000 14000 4000 4000 "clearline"] + Line[128000 14000 133000 19000 4000 4000 "clearline"] + Line[133000 19000 133000 35000 4000 4000 "clearline"] + Line[133000 35000 136500 38500 4000 4000 "clearline"] + Line[136500 38500 146500 38500 4000 4000 "clearline"] + Line[146500 28500 148000 27000 4000 4000 "clearline"] + Line[148000 27000 166000 27000 4000 4000 "clearline"] + Line[166000 27000 166000 42000 4000 4000 "clearline"] + Line[166000 42000 169000 45000 4000 4000 "clearline"] + Line[169000 45000 179500 45000 4000 4000 "clearline"] + Line[179500 55000 179500 98500 4000 4000 "clearline"] + Line[179500 98500 205500 124500 4000 4000 "clearline"] + Line[89000 142500 107500 124000 4000 4000 "clearline"] + Line[107500 124000 127000 124000 4000 4000 "clearline"] + Line[127000 124000 127000 110000 4000 4000 "clearline"] + Line[127000 110000 138500 98500 4000 4000 "clearline"] + Line[138500 98500 146500 98500 4000 4000 "clearline"] + Line[146500 78500 132500 78500 4000 4000 "clearline"] + Line[132500 78500 132000 78000 4000 4000 "clearline"] + Line[132000 78000 121500 88500 4000 4000 "clearline"] + Line[121500 88500 116500 88500 4000 4000 "clearline"] + Line[63000 86000 63000 72000 4000 4000 "clearline"] + Line[63000 72000 67000 68000 4000 4000 "clearline"] + Line[67000 68000 82500 68000 4000 4000 "clearline"] + Polygon("clearpoly") + ( + [257000 147000] [169000 147000] [169000 10000] [257000 10000] + ) +) +Layer(3 "GND") +( +) +Layer(4 "power") +( +) +Layer(5 "signal1") +( +) +Layer(6 "signal2") +( +) +Layer(7 "signal3") +( +) +Layer(8 "signal4") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/1.2.7/doc-orig/gcode.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode.pdf =================================================================== --- tags/1.2.7/doc-orig/gcode.pdf (nonexistent) +++ tags/1.2.7/doc-orig/gcode.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode.png =================================================================== --- tags/1.2.7/doc-orig/gcode.png (nonexistent) +++ tags/1.2.7/doc-orig/gcode.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode_control_img.eps =================================================================== --- tags/1.2.7/doc-orig/gcode_control_img.eps (nonexistent) +++ tags/1.2.7/doc-orig/gcode_control_img.eps (revision 13657) @@ -0,0 +1,711 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: GIMP PostScript file plugin V 1,17 by Peter Kirchgessner +%%Title: gcode_control_img.eps +%%CreationDate: Mon May 30 02:37:26 2011 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%Pages: 1 +%%BoundingBox: 0 0 404 231 +%%EndComments +%%BeginProlog +% Use own dictionary to avoid conflicts +10 dict begin +%%EndProlog +%%Page: 1 1 +% Translate for offset +0 0 translate +% Translate to begin of first scanline +0 230.40000000000001 translate +403.20000000000005 -230.40000000000001 scale +% Image geometry +1680 960 1 +% Transformation matrix +[ 1680 0 0 960 0 0 ] +currentfile /ASCII85Decode filter /RunLengthDecode filter +%%BeginData: 51668 ASCII Bytes +image +JcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqR +JcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqR +JcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqR +JcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqRJcDqR +nG`K=^]4@!KE(H@!._ib!'c,9nG`K=^]4@!KE(H@!._ib!'c,9nG`K=^]4@!KE(H@!._ib!'c,9 +nG`K=^]4@!KE(H@!._ib!'c,9nG`K=^]4@!KE(H@!._ib!'c,9nG`K=^]4@!jSo5LklA9onG`K= +^]4@!jSo4qkl:]J])V:"!._ib!'fQEkPtSn])V:"!._ib!'fTF!<20^!!g+8nG`K=^]4@!jo5>Y +kPtSb])V:"!._ib!'fTF!;PaX!!0\2nG`K=^]4@!jo5>Mk5`*nnG`K=^]4@!jo5>=k5YL3]DqC# +!._ib!'fTF!5Rat!'e*qnG`K=^]4@!jo5=2k5YK(]DqC#!._ib!'fTFjo>Al]DqC#!._ib!'fWG +!<2*\!!g.9nG`K=^]4@!k5PGZjo>A`]DqC#!._ib!'fWG!;P[V!!0_3nG`K=^]4@!k5PGNjT)pm +nG`K=^]4@!k5PG>jT#:1]`7L$!._ib!'fWG!5R[r!'e-rnG`K=^]4@!k5PF3jT#9&]`7L$!._ib +!'fWGj8]/j]`7L$!._ib!'fZH!<2$Z!!g1:nG`K=^]4@!kPkP[j8]/^]`7L$!._ib!'fZH!;PUT +!!0b4nG`K=^]4@!kPkPOirHalnG`K=^]4@!kPkP?irB(/^&RU%!._ib!'fZH!5RUp!'e0snG`K= +^]4@!kPkO4irB'$^&RU%!._ib!'fZHiW&rh^&RU%!._ib!'f]I!<1sX!!g4;nG`K=^]4@!kl1Y\ +iW&r\^&RU%!._ib!'f]I!;QKm!"\Dqr;Zfu^&RU%!._ib!'f]I!:]pe!$CP,!.b"J^&RU%!._ib +!'f]I!9!eU!'ffL!5SO5!.V`_nG`K=^]4@!kl1Xur;ZhIli-tCr;Zg^^Am^&!._ib!'f]I!.b"J +lMgkRr;Zg>^Am^&!._ib!'f]Ir;ZfulMgkZr;Zg.^Am^&!._ib!'f`J!<2os!!DNd!;ucq!!g7< +nG`K=^]4@!l2Lb]r;Zg&lMgk`r;Zg"^Am^&!._ib!'f`J!;QKm!"\>or;Zfu^Am^&!._ib!'f`J +!;QKm!$CJ*!.b"J^Am^&!._ib!'f`J!:]pe!'f`J!5SO5!.Vc`nG`K=^]4@!l2LbQr;ZhIl2LbA +r;Zg^^]3g'!._ib!'f`J!9!eUkl1YPr;Zg>^]3g'!._ib!'f`J!9!hV!!2<`!;QKm!"ZjEnG`K= +^]4@!l2LbArVup#kl1Y\r;Zg&^]3g'!._ib!'f`J!9!hV!!h`f!<2os!!C"9nG`K=^]4@!l2LbA +rVup/kPtJ\!!0k7nG`K=^]4@!l2LbArVup?kPkO4r;aV4nG`K=^]4@!l2LbArVup_kPkOtr;ZhI +_#Np(!._ib!'f`J!9!hV!.X23!9!eU!'e:!nG`K=^]4@!l2LbArW)*\!:]pe!$B#VnG`K=^]4@! +l2LbArW)*\!;QKm!"ZmFnG`K=^]4@!l2LbArW)*\!;ucq!!g=>nG`K=^]4@!l2LbArW)*\!<2os +!!C%:nG`K=^]4@!l2LbArW)'[r;Zfu_#Np(!._ib!'f`J!9!hVjo5=2r;aY5nG`K=^]4@!l2LbA +rW)'[!5SO5!.VibnG`K=^]4@!l2LbArW)'[!9!eU!'e="nG`K=^]4@!l2LbArW)'[!:]pe!$B&W +nG`K=^]4@!l2LbArW)'[!;QKm!"ZpGnG`K=^]4@!l2LbArW)'[!;ucq!!g@?nG`K=^]4@!l2LbA +rW)'[!<2os!!C(;nG`K=^]4@!l2LbArW)$Zr;Zfu_>j$)!._ib!'f`J!9!hVjSo41r;a\6nG`K= +^]4@!l2LbArW)$Z!5SO5!.VlcnG`K=^]4@!l2LbArW)$Z!9!eU!'e@#nG`K=^]4@!l2LbArW)$Z +!:]pe!$B)XnG`K=^]4@!l2LbArW)$Z!;QKm!"ZsHnG`K=^]4@!l2LbArW)$Z!;ucq!!gC@nG`K= +^]4@!l2LbArW)$Z!<2os!!C+^L+ +mf*9;r;Zg"i;`i!!!9%rrD!V!;c]q_#"-#s7u]q&+9GtJGfHJ"5s4Krr@Sc!!*?( +mf3=ir;QcTrW)fp!5SI3n,EBPmr;QcTrW)fp!5SI3n,EC_ +qZ$U,n,ECcqZ$VGiW&EI!._lc!>"tn!!%NIrrD!V!;c]q_#"-#rrDuo!!!PurrDuo!!%N-s7$$g +JAD3d&,>Pm!.XtI!9!hVqYpQ2qZ-*b!;u]o!"\Pu!;u]o!.Wu-nG`K=_#OKHq!J+^5Q1T^i;N`Q +rrBk3!:Tpfr;-Ho&+BMur;-HoJ)UFsrr@Sc!!*W*mJm5OrVllUrW)fp!5SI3n,ECcqZ$U,n,EC_ +qZ$U\iW&EI!._lc!>"tn!!#7^rrD!V!;c]q_#"-#rrDuo!!!PurrDik!!#7Bs7$$gJAD3d&,>Pm +!'gG^!9!hVqYpQ2qZ-*b!;u]o!"\Pu!;QEk!'fHBnG`K=_#OKHq!J+^+8u3>i;N`QrrBk3!:Tpf +r;-Ho&+BMuq"k$k5N2Y3rr@Sc!!*W*mJm5/rVllUrW)fp!5SI3n,ECcqZ$U,n,EC_qZ$U\iW&EI +!._lc!>"tn!!",>rrD!V!;c]q_#"-#rrDuo!!!PurrDik!!#7Bs7$$gJAD3d&,>Pm!$D1>!9!hV +qYpQ2qZ-*b!;u]o!"\Pu!;QEk!'fHBnG`K=_#OKHq!J+^+8u3>i;N`QrrBk3!:Tpfr;-Ho&+BMu +q"k$k5N2Y3rr@Sc!!*W*mJm5/rVllUrW)fp!5SI3n,ECcqZ$U,n,EC_qZ$U\iW&EI!._lc!>"tn +!!",>rrD!V!;c]q_#"-#rrDuo!!!PurrDuo!!%N-s7$$gJAD3d&,>Pm!$D1>!9!hVqYpQ2qZ-*b +!;u]o!"\Pu!;u]o!.Wu-nG`K=_#OKHq!J+^+8u3>i;N`QrrBk3!:Tpfr;-Ho&+BMur;-HoJ)UFs +rr@Sc!!*W*mJm5OrVllUrW)fp!5SI3n,ECcqZ$U,n,ECcqZ$VGiW&EI!.`8n!!2us!<2rt!>"u) +!!#7ZrrE&q!!#7^rrD!V!;c]q_#"-#rrDuo!!!PurrE&q!9!nHrr@Sn!!!,ts8E!!&,?,(!'g;Z +!<2iq!'gG^!9!hVqYpQ2qZ-*b!;u]o!"\Pu!<2iqi;`EquHZp!9!hVqYpQ2qZ-*b +!;u]o!"\Mt!.b"J!!D0ZnG`K=bQ%VbqZ$d%huE`fq#16n5PY6YJG]EFrrD!V!;c]q_#"-#rrDuo +!!!Ptrr@TJ!!!8^s7$$gJBRun+8Z$A"5j.Z&,?,(!'g8Y!5SO5!!3#t!9!hVqYpQ2qZ-*b!;u]o +!"\Mtqu?^-i;`!!NJ_!!!Q)rVup_mJd1ErW(%>!5SO5 +!.Wl*nG`K=f)Pf#pAb!i"U!Z_!"\l(!!#7NrrD!V!6G0?JGfK(s7$$gJCaeos8)d""5j.Z&,?,( +!'flN!9!hVaT)2=!!1pUnG`K=fDkmPp&Fmh"U!Z_!"\l(!!#7NrrD!V!6P6@rqufs"5X"Hrr@T% +!!39&r:'aj"5j.Z&,?,(!'flN!9!hVao;A=r;Zg&h>d!E!.`]%!XJbpnGi^phuE`fq#16n5OJIN +i;N_urrDim!!!Pcs7$$gJCji'&-'H8!!NJ_!!!Q)rVup_mJd1ErW((?!:]pe!$C%snG`K=fDksp +s+'V>"U!Z_!"\l(!!#7WrrMToqYpQRrW)]m!<@W"rrD!U!!#7>s7$$gJCji&5QC3Q"U!Z_!"\l( +!!#7Ws8N'!J,B6G_#=?/rrVZi#M&hS_#465J)1.orr@T%!!.TKn,NUohuE`fq#16n5PP0[qu?^= +qu6YHrW)`n!l+d:ec,W"r;bXQnG`K=fDksPr9s[i"5j.Z&,?,(!'g5X"7Q9j#Q+Q"!;QTn!!%N" +s8;ot!Sm_Err@TH!<<'!^u>=q!WVra!!NJ_!!!Q)rVup_p\t?2!!!&trrE&s!;ZWpr;HZr+4pMm +rqufs"5NqGrr@TI!!=>Cs8M!X!X&Jln,NUohuE`fq#16n5PP0XJGoQHrrDuq!;ZWpq#16n&(gg] +r;?Tq#Mf@Krr@TJ!!!-"rrDQK!!3E*i:$^M"5j.Z&,?,(!'g5Xr;ZhIrVllmr;cZn!:]sf!!h-U +!;QKm!"[lbnG`K=r;Zg.rVllqirB,ks1n+("U!Z_!"\l(!!#7YrrE&s!!#7^rrDQe!;ZWpi;N]V +"5!PQnGN=e+5Hncrr@TJ!!%NHs5O(\+9-l\!!NJ_!!!Q)rVup_q#:?lr;Zg>rVllUr;cZn!5SR6 +!!1^O!9!eU!'f9=nG`K=rVup!qu6ZSj8]3Fs6fpk"5j.Z&,?,(!'g8Y!;QKm!"]&.!5SR6!!2oq +!.b"JfDbidr;ZhIh#HmD!.b%K!!iE$!;PUT!It+;!!NJ_!!!Q)rVup_q#:?`r;Zg&rVlkJrVup! +q>^?m!.WZ$!.b"Jg]-dC!.b%K#9X!G^]FK8ro=%[s8;_s7l$_"U!Z_!"\l(!!#7YrrBk,!!!,t +rrDup!!"+orrE&s!!!,Us7$$gJGoQKrr@TK!<<'!^ubUu"97lZ!!NJ_!!!Q)rVup_q#:?0oDejr +qYpQnqu?^=g&D'Mr;Zg&g]-dC"b6RQ!WW)r!!48Bi8t"@#QN`N!!NJ_!!!Q)rVup_q#:>EoDek% +qYpQjqu?^-g&D'Ir;Zg.g]-dC"b6RQ#QN`\!!39&puVPX&-'H6!!NJ_!!!Q)rVup_q#:>EoDek5 +qYpQjqu?^-g&D'Ar;Zg>g]-dC"b6RQ&-%1X!!3,tjo>H)s+'P<"U!Z_!"\l(!!#7Ys763j5PkB[ +nGE7d#MK+Wi;EWU5MQ5-rrdiP!$D4;!!,=`jo>EHs6]jj"5j.Z&,?,(!'g8Yo)Jc?qYpQbqu?^% +g&D&fr;ZhIg]-dC"FpIPJ,K0D!?_@(!!.TKmJmCmhuE`fq#16n5PbUHooDejnq>UHQqu?^!gA_0Pr;Zg"gAg[B +"FpISs+'qG!WVZQ!!39&nEp8["5j.Z&,?,(!'g;Z!<2Tj!!i?"!9!bT!!CsT!;ucq!!h6XnG`T@ +!!iQ"!!.TEkPtYhs5<;F"U!Z_!"\l(!!#7ZrrDuh!!!Q*rrBk4!!!&RrrDim!!!P`s7$$jJ,g,X +q#CF;r9++^&-'H5!!NJ_!!!Q)rVup_q>UHmoDek5q>UH1qu?]tgA_0Br;Zg>gAg[B"+U@nq"Xmj +&,tbm![%GmmJmCmhuE`fq#16n5Pb;!<`Ac!!.TK +r;Zg"q#C3k"U!Z_!"\l(!!#7ZrrDuh!;QQo_#+04!S[PRJGfK$s7$$jJ,k)7q#CHss+'>6!WW)r +!!!9!s8)d""5j.Z&,?,(!'g;Z!;uKi!!2lp!5SL4!!1gRr;Zfug&LRA"+UCOJG9*Fs1mn"!Wi>r +r;Zg.q#C3k"U!Z_!"\l(!!#7ZrrDui!!!,rrrBk4!!!&SrrE&s!!!,Ss7$$iJ-#]E!!.T-l2Ukf +s7#se!$D"9qZ$d%huE`fq#16n5Pb"tj +!!,=ar;ZfunG`XL!!!Q)rVup_q>UHoo`+uAq#:?Pqu?^!g]%8hr;ZhIg&LRA!e:gNpAb4!r9=7_ +J,]BH!!D`j"Mb!;&,?,(!'g;Z!<2Wkp\t6Oqu?^!g]%8(r;bLMnG`Q?&)d0^!<`8b!!3,tr;Zm( +s5<_R!!iB#"FpIP&,?,(!'g8Yp&G'np\t6_qu?^%g].3P!!1aPnG`Q?+5lkn!<`>e!!33$q#(0o +&-'HA!!!,ts8E!!&,?,(!'g8Yp&G'pp\t6_qu?^%h#@BRr;Zg"f`1I@!e;B.pAb3prp'Oc"97lh +!!48BJG9*EJ,]HKrUBdd!>"u)!!#7Yrr@TD!!!8urrDil!!!PbrrDuq!!!8Vs7$$iJ3UjD!!*-# +lMptks5=Hr;ZkJrqHHs!WW&us8Mrs!C-AY!!#7YrrBk/!!#7XrrDup!!"+rrrDQe!!"+ns7$$h +J:I4l!IoXd!!48BJGfHKs8;Wl"UG(C!$D7>!!,=ZrVup_q#:?0pAjpe!;u`p!$C"r!9!eU!'f-9 +nG`N>J+WdBIt6kc!C-V_!!33$q"Ogl&,uV0#Q+N$q#16n5PY6Yi;EWU"7cBkrql`r5MZ8=_#465 +J(XejrrIZLo`,"W_!D%%J,]BH!X&Jlp](F=qu?]tqu6ZkrVup_q#:?`r;Zg&nGiCd!.Wf(!.b"J +fDk@?!J(1B!!,="li7(dr;?Ts#QN`W!!,=RrVuqJr;QcdrVup_q#:?hr;Zg.nG`K=r;bUPr;Zfu +fDk@?!J11A!!+2"m/R1is7lNm!Y>=Hp](=Zi;N]V5Q(N]i;N]V5PY6Yr;?Tq+7T:1_#=<6!Sm\T +rqufs"5!SBrrI]Ko`,"7i9^LG#QO;l!!48BJG9*FJ&)$`!$D.=!5SR6!'g8Y!<2os!'fuQ!9!hV +!!D$V!;ucq!!h-UnG`N?r:L$j+5lMd!XJb`r;Zj_s7ZKos+((K!"]#-!.b%K!'g5Xr;ZhInG`LX +rVup'h#@BLr;Zg.fDk@?!J1%=!!*Vgm/R1us1nR5!It+D!!*-#r;Zg&r;Z]q!'g5X!.b%Kn,EC_ +rVup/h#@BDr;Zg>fDk@?!JC1?!!*W"m/R20s+(%J!WW)m!!*-"r;Zg"rVllsr;Zg^p\t?2!!!&g +rrDur!!"+rrrD!U!!#78s7$$hKD>*>!>"\e!!+2Ar;Zm"s7l?h!<`8u!!!&urrDuq!!#7Xrr_`j +!!hrlrVuqJh#@Air;ZhIfDk@?!JBn7!!*>om/R/Orqufu"97lc!!*2squH]q!;QKm!'g5X"8i-! ++7B.1^]4Dirr@TJ!7q2>rrIcAo`,!tnEg2V5Q(H[!XJb`p](="nFHV[J+ipB!!%N:rrVZi#M]:W +!!!&Ns7$$hKCJO6!=/,]!!,=Zr;Zm0s1nC0!=/,c!!%NBrrMTom/I(dJ)(&(rqufs"4mMArrIo5 +o`,!pq!A%^J+3C:!?_@9!!*Vgo)Q9"!;ucq!!h*TnG`NEi:R'N"8M6`!Is&+!!,=`pAb4)i:?rX +rrDim!!!P\s7$$hLZ%h*!<`,a!!.Sbr;ZkJr:^0l&&@f;!!0S/!:]pe!$BelnG`NEi:R'N"8M6` +!WTt6!!3,ppAb4)_"7U,"1S:1i;EWU5M#l(rrIo5o`,!pq!A%^s+((K!Wi>jpAb49JFigA#Ij^5 +_#465J(FYhrrIo5o`,!pq!A%^s+((K!X&J\pAb49JFigA&%DQ=JGfJus7$$hLVWQ_!'^#OMHk +!.Wi)!<2os!!CdOnG`NM_"@[.!W;?c![KQr;Zg& +ec5.=!KY%h!!*,umJm7gs8;ou5Q:?V!'g&Tp&>-l!!",/rrTt9!T!bUq#(0m&(U^LrrJ1ro`,!n +r9aOc!WW)u!It%@!!#7U!!!&mrr_`j!!hrlrVuqJhZ!TFr;Zg>ec5.=!KY%h!!*,umJm7gs8;ou +s7l9f!'g)U!!Doo"2Fm:!Up$gr;HZr+5["ti;EWU5Lof'rrJ1ro`,!nr9aOc!WW-!!Wi>jp&G(W +oDejrp&>#BrW)Ee!;QNn!"[rd!5SO5!.WQ!nG`NM_"@[.!W;?c!#BquHQm!<2Tj!"\#f!.b"Je,Sq;!JfV+!!*2smJm7gs8E!!#Q45p!>!!>!!",6rr@TI +!;ZWpr:Bsh&)dKd!!!&Ks7$$hLZ%h*!<`,b!!*-#rVus(r:L$j&)d-]!'g/VqZ$VGqYpQjoDejr +iVroWr;Zg"e,Sq;!JB>'!!*2kmJm7gs8E!!#Q45p!=.QV!!%NAs8)crJ,90FnFQ\\#N>[_r;?Tq +#Li_BrrIcAo`,!tnEp8W!WW-!!=/Pq!!*>opAb0op&>$kqZ$U\qYpQRoDejniVroQr;Zg.e,Sq; +!JBn7!!*>omJm7gs8E!!#Q45p!<_ic!!!8srrE&q!!#7[rrBk,!!!,[rrDQe!!"+is7$$hKCJO6 +!=/,^!!*-#rVus(r:L$j"8Mcon,ECeqZ$U\qYpPGoDejniVro9r;Zg^e,Sq;!JC1?!!*W"mJm7g +s8E!!#Q45p!Ie<[A5Ci/%!$iqZ$U$VrqcZq5Q(N]q!nCb"8DfqpuqbY"4@/$kqZ$U\r;Qcdnc/Xlp\t6_kl:\gdJr_9!e:g>pAb3rr9XIb +!WW-!!=/Po!!!Q/rrBk4!!#7VrrE&q!!#7]rrD!J!!!,qrrD!A!!!PWs7$$iJ.LT4!!*3"m/R.f +s8E!!#Q4/n!"])/!5SL4!'g,UqZ$VGr;Qc4nc/Xpp\t6/kl:]*dJr_9!e:OFpAb4!q!A%^!WW-! +!=/Po!!",?rrD!T!!#7Us8)crJ,Kf!!*-#rVus(r:Bsi5N)M@!C-)P!!#7UrrDuq!!",=rrD!U!;c]q_#=<6!VcToJE[%65LBH" +rr[cO+7T(+!=/Vj!!*-#rVus(r:BsiJ&)$`!?_+8!!#7UrrE&s!!#7]rrD!V!!!&rrrD!V!!!,q +s6'F_J'e5brr[cO&,>r#!>#+p!!*-#rVus(r:Bsis+((K!>#,,!!#7Ts8;otJ,K:li7%es8E!! +#Q45p!<`,p!!*&t!!#7Trr`0!!$D+_#=<65O&1Ji;N`BrrDin!!!P@s7$$gJGoNM5Q?95!<<)a!!*-#rVus(r:L$j +++X7h!>",f!!#7JrrD!V!:0Xbq#16n+1hLArr@TK!!aVGn,NFns8M9`!_rVup_o)J^i!.XnG +!9!hVq#:Eb!!i8u!;QNn!'e'pnG`K=r;Zg.rVllqkl:_bs8E!!#Q45p!'g>\!=.Q^!!#7Trr`0! +!$D+\!=/,n!!#7T +rr_`j!!iE$!9!hVq#C\!=/,n +!!#7Ts8;otJ,K-!WW-!!=/Pq!!#7\!!*>orVup_ +o`"pjr;Zg^r;QcTrW)co!9!hV!!E#r!;QNn!'e'pnG`K=hZ*ZXs8E!!#Q45p!$D(UGFr;cWm!;QNn!'e'pnG`K=hZ*ZXs8E!!#Q45p!?Zji!!*VgrVup_o`"p\ +r;Zg&r;QcTrW)coqu?_Hq>UHirVup_])V:"!.`r,!UHirVup_])V:"!.`r,!UHirVup_])V:"!.`r,!UHirVup_])V:"!.`r,!!!D!!+1WrVup_o`"oAquHZp +!9!hVqYpQjqu?^-q>UHirVup_])V:"!.`r,!UHirVup_])V:"!.`r,!UHirVup_])V:"!.`r,!$VrqcZq5Q1T^i;N`Q +rrD!T!!!,srrDin!!#6ps7$$gJDU>-!WW-!!=/Pq!!*2squ?`sr;Zg^p&>$kqZ$U\rVllUrW)fp +!9!bT!!E&s!;QNn!'e'pnG`K=hZ*ZXs8E!!#Q45p!UHirVup_])V:"!.`r,!!9!hVqYpQ2 +qu?]tq>UHirVup_])V:"!.`r,!i;N`QrrBk4 +!!!&qrrDin!!#6ps7$$gJDU>-!WW-!!=/Pp!!.S"rVus0q#(0m5PtH\i:R'M+8u3>i;N`QrrBk4 +!!!&qrrDin!!#6ps7$$gJDU>-!WW-!!=/Pp!!,="rVus@nGN=e5PtH\_"@[-+8u3>i;N`QrrBk4 +!!!&qrrDin!!#6ps7$$gJDU>-!WW-!!=/Pp!!,=BrVus`i;EWU5PtH\JFrmB+8u3>i;N`QrrBk4 +!!!&qrrDin!!#6ps7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655PtKQ!!",>rrD!V!;c]q_#+04 +!Vu`qq#16n5J$marr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7]rrE&j!!",>rrD!V!;c]q_#+04 +!Vu`qq#16n5J$marr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7]rrDuh!!",>rrD!V!;c]q_#+04 +!Vu`qq#16n5J$marr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7]rrDid!!",>rrD!V!;c]q_#+04 +!Vu`qq#16n5J$marr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7]rrDQ\!!#7^rrD!V!;c]qi;-!WW-!!=/Pp!!+22rVutK_#4655Q1T^q""L`rrD!V!;c]qq"t*l&,Q;+q#(0m +5J$marr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7^rrDQ\!!!&trrD!V!;c]qr;6Np+8Z!;nGN=e +J%G[Lrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7^rrD!L!!!&trrD!V!;c]qr;6Np+8Z!;i;EWU +J%G[Lrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7^rrBk,!!!-!rrD!V!;c]qrql`r5PkB[_#48D +s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q1T^JFigA#Q4T%i;N`Ps82isJ,90FJGfJYs7$$g +JDU>-!WW-!!=/Pp!!+22rVutK_#4655Q1WR!!!Q-rrD!V!;ZWpJGfKDs8;ot!P/7"rr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrE&i!!",=rrD!V!;ZWp_#=<6!W)frrqufs"1eI$rr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrDug!!#7]rrD!V!;ZWpi;N]V"8`#tr;?Tq#J'm(rr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrDic!!%NHrrD!V!;ZWpnGWCf#Q"H#q#(0m&%V`0rr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrDic!;lcri;N`PrrDin!!!Q+rrDQe!!"+Os7$$gJDU>-!WW-! +!=/Pp!!+22rVutK_#4655Q:Z_nFQ\\!W2lsi;N`PrrDur!!",;rrD!U!!#6os7$$gJDU>-!WW-! +!=/Pp!!+22rVutK_#4655Q:Z_nFQ\\#Q+N$i;N`Os8DuuJ,90F_#465J%>UKrr@T,!!*-#rVus( +r:Bsi+7T70!Iqo`!!#7_rrD!U!;lcuqu?^=qu6ZSrW)`n!l+d:q>UGFr;aA-nG`K=hZ*ZXs8E!! +#Q42o!?^h1!!.Sbr;Zg^rr2uVrVup!qZ$Qq!.XnG!9!hVq#:Eb!!i?"r;Zfu\Gu'u!.`r,!nG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sb +r;Zg^rr2uVrVup?nc&U)rW)Bd!:]pe!$A`NnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uV +rVup_nc&T>rW)Bd!9!eU!'e!nnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrVuqJnc/Of +mf*:&r;ZhIp\t9`#K6Z3rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!:g'hrquibrr@TJ +!;?Hm!!%Mfs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`HrrDuq!:Kmc!!!&orr`0! +!$B2[nG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)co!Up?krrDim!;HKo!.XnG!<2os +!!Duq"7Q9j#K?`4rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;ZZp!!%NHrrDQe!;QQq +n,N^jrrDuq!!!8urr^%:!!1(=nG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)fp"8i-! ++8l-=i;EZNrrTt9!W2lsq#(0m&,6)(JGoPfs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_ +i;N`Qrr_`j!!iH%!5SR6!!2lprVuqJr;Qcdr;Zg>p](0l!.W#gnG`K=hZ*ZXs8E!!#Q42o!?^h1 +!!.Sbr;Zg^rr2uVrW)fp"2Fm:!W;rtJGoNK!Vu`qr;HZr+8l-=i;EWU5PY6Yrqufs5K<`mrr@T, +!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;c]qJGoQHs8;ot"8Vrsq#16n&,cG-_#465J,'$D +r;?Tq+3+?Mrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;c`o!!%NJrrE&s!!!,srrDQf +!!!9%rr@TJ!;HKnq#(0m&'"Y=rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcrrqufs +5Q:Z_r;?Tq#PnB"i;N]V"8r2t!!!&orrDQe!!!8Ds7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`RrrDuq!!",?rrDim!!!Q*rrBk6!!!&urrE&s!!!,qrrD!U!!!,@s7$$gJDU>-!WW-! +!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrDid!!",:rr@TA!!!8urrBk+!!%Mqs7$$gJDU>-!WW-! +!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrDQ\!!#7Zs763j&,6)(_".O++41&Wrr@T,!!*-#rVus( +r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcri:I!LJ,90Frpp*i+8>d8JF`a@#LNM?rr@T,!!*-#rVus( +r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcr_"7X&rrDug!!#7Xrr@T@!!!,Js7$$gJDU>-!WW-!!=/Pp +!!+22rVutK_#4655Q:Z_i;N`RrrBk-!!!&qrrDug!!%NCs7--i!RUl9rr@T,!!*-#rVus(r:Bsi ++7T70!Iqo`!!#7_rrD!V!;lcrJFrmB"8Vrsq""LZs7$*9s7$$gJDU>-!WW-!!=/Pp!!+22rVutK +_#4655Q:Z_i;N`Rrr@TB!!!9"rrDid!!!&orrE&g!!%Mrs7$$gJDU>-!WW-!!=/Pp!!+22rVutK +_#4655Q:Z_i;N`Rs7?9k&,H5*nFQ\\"8Dfqrp]sg5LKN#rr@T,!!*-#rVus(r:Bsi+7T70!Iqo` +!!#7_rrD!V!;lfg!!",:rrDQ\!!!8urrE&g!!"+gs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`SrrE&j!!#7ZrrD!L!!!Q(rrE&g!!!PWs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`SrrE&j!!%NErrD!L!!",8rrDue!!!8Os7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`SrrE&j!;QQoi:I!L5PP0Xr:'ae"4@/-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`S +rrDuj!!!&orrBk-!!%NBrrE&f!!!&Js7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`S +rrDuj!!!,qrrBk-!;6?lrpKj8s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&l +!!!8urrD!N!!!&mrrE&e!!%Mts7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&l +!!!Q(rrD!N!!!,ns6fpf5L]Z%rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;uisrq6d8i:[-N#PA&b!!"+is7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&l!!#7X +rrD!N!!!Q%rr@T=!!!PYs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rs7QEmJ+rsC +nFch^+8#R5JFEO=#Li_Brr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lfj!!!&nrrDQ^ +!!%N@rrBk(!!!,Ms7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rrr@TE!!!8trrDig +!!!&krrBk(!!!&Ks7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rrr@TI!:g'hq"t*l +&+9Gti;EWU"8VrsJGfJss7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrBk5!!!&i +rrDup!!",/rrDQe!!!9"rrBk5!!%Mus7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`R +rrBk5!!!&irrDup!!",/rrDim!!!Q*rrD!U!!#75s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`RrrD!U!!!,krrE&r!!#7OrrDuq!!",:rrDQe!!#75s7$$gJDU>-!WW-!!=/Pp!!+22 +rVutK_#4655Q:Z_i;N`RrrDQe!!!8ns82isJ+!=:rqufs5Pb[rr@T,!!*-#rVus( +r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcrq#(0m&+KT!JGfK7s8;otJ,0*Er;?Tq+4U>[rr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcrr;?Tq+7T:1_#=<6!UTgdJGoQDrrE&s!!!PZs7$$g +JDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrE&s!!#7QrrD!V!!!,frr^%:!!2ior;Zg. +eGo%^Hp!.XG:!q60pli.(&!!!&orrDur!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_ +i;N`PrrMTom/I(dJ*[+:^]4?8p\t6mrVup/eGo%-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`!rr^%: +!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW(+@"2Fm:!VcTorr)lt +&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!6Y-!WW-!!=/Pp +!!+22rVutK_#4655Q:Z_i;N`!rr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sb +r;Zg^rr2uVrW(+@"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V +!;ZWqn-A=[!<@W8rr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uV +rW)corr<%Kmf*@X!!hii"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_ +rrD!V!;c]tqu?^=mf*@(!!2Ec"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo` +!!#7_rrD!V!;c]tn,NFnmf37d!.XA8"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70 +!Iqo`!!#7_rrD!V!;c]t^]4?8n,ECcrVup?m/I1'!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp +!!+22rVutK_#4655Q:Z_i;N`Qrr@TK!:Tpfq#16n&+';u^]4?8p\t6mrVup/eGo%nG`L(rVup!m/I1'!!!&o +rrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrDim!!!Q+rrMU2q>UGF +r;c3a"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcrnGN=e +#Q"H$^^']8qu?_HmJd:(!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_ +i;N`RrrD!U!!!,trrE*#qYpQpqu?^]mJd:(!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22 +rVutK_#4655Q:Z_i;N`RrrBk+!;c]qr;6Np+79(1^]4?8p\t6mrVup/eGo%- +!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rrr@T@!!#7\rrDil!!!Psrr^%:!!2io!<2rt!"[TZ +nG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iq!.aY@!$D+-0!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&h!!!,u +rrD!L!!!,orr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)lr +!<2Nh!!2us!9!JL!!2cm"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_ +rrD!V!;uisrp^!crrD!K!;6?o^]4?8p\t6mrVup/eGo%-!WW-!!=/Pp!!+22 +rVutK_#4655Q:Z_i;N`SrrDue!!#7]rrBk+!!#7Wrr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!! +#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)lr!;u?e!$D.=!5S1+!$Cq7"2Fm:!VcTorr)lt&(LXKrr@T, +!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;uisr:'ae&,cG-_".O+&,-#*^]4?8p\t6mrVup/ +eGo%-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrDue!!!-!rrBk+!!!,p +rr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)lr!;u?e!!3#t +!5S1+!!2fn"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;uis +r9s^arrBk*!;?Ep^]4?8p\t6mrVup/eGo%p\t?2!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`SrrDud!!#7^rrBk*!!#7Xrr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1 +!!.Sbr;Zg^rr2uVrW)lr!<2Hf!$D1>!9!DJ!$Ct8"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus( +r:Bsi+7T70!Iqo`!!#7_rrD!V!;uisrpTmf&,lM.i:6jJ&,6)+^]4?8p\t6mrVup/eGo%-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&f!!!-"rrD!J!!!,qrr^%:!!2io +!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iqn,NFhrVllenc/Xlp\t?2 +!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rs6fsdrrDQZ!!!&o +rr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iq!.aP=!.Y"J +!;Q*b!!2io"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcr +JFEO=5Q:Z_q!e@Yrr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uV +rW)iq!5S((!$D4?!;u?ep\t?2!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`RrrBk(!!!Q/rrDue!;HKq^]4?8p\t6mrVup/eGo%^Bn!!3&u!.aV?p\t?2 +!!!&orrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrDuq!!",:rr@TJ +!<)ot_#=<6!W)frJGoQCrr^%:!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^ +rr2uVrW)iq!<2os!'g;Z!5SO5!.Y"J!9!hV!!E)t!5SR6p\t?2!!!&orrE&t!!!PZs7$$gJDU>- +!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Qs8;otJ,0*Ei;EWU5Q:Z_nGWCf#Q"H#i;N`Nrr^%: +!!2io!<2rt!"[TZnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)fp!.b%Kq#:?`r;Zg> +rr2unrVup/qYpQRrW)]m"2Fm:!VcTorr)lt&(LXKrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_ +rrD!V!;c]t^]4?8q#:?hr;Zg.rr2urrVup?qYpQRrW)]m"2Fm:!VcTorr)lt&(LXKrr@T,!!*-# +rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;c]tn,NFnq#:?lr;Zg&rVuis!.XkF!9!hVp\t?2!!!&o +rrE&t!!!PZs7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Qrr`0!!$D"9!<2os!!E3" +!l+d:q>UHQrW)]m"2Fm:!VcTor;HZr#LreCrr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V +!;ZZp!!%NCs8;ot!WE$"n,N^hrrD!V!;HKq^]4?8p\t6grVup#eGo%UKb#PS/tJGfKGrrE+Lq>UHQrW)]m"2Fm:!VcTonGWCf!S%/=rr@T, +!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!:9^c_#465J+N[?i;N`Nrr^%:!!2io!9!eUeGo%< +!.`r,!-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Bs8;ot +!V?-!WW-!!=/Pp!!+22rVutK +_#4655Q:Z_i;N`Ps8N'!J+imB_#46:J,fQ- +!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Qrr`0!!$Cq7!9!eU"[E%e^]4E2rrD!V!;HKq^]4?8 +q#:?hqu?^!ec5.=!.`r,!rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;c`o!!%NCrrE&s!!39&nGWCf#Q"H# +i;N`Nrr^%:!!2lp!:]md!!1XMnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iq!<2os +!'g2Wr;Zm"s5-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`RrrDQe!!!8trrD!U!!#7]!!%NG +rrD!V!;HKq^]4?8q#:?PqZ,1HnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iq!9!eU +!!Drp!:]pe!$;%-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rrr@TE!!!,urrE&m!!!Q,rrD!V!;HKq^]4?8 +q#:?PqZ,1HnG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)iq!.ahE!!2rrpAb1(qu6ZS +rW)]m"2Fm:!VlZpi;3N)s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rs7QHhrr@TE +!!!9$rrD!V!;HKq^]4?8q#:?`qu?]tec5.=!.`r,!-!WW-!!=/Pp!!+22rVutK +_#4655Q:Z_i;N`SrrE&l!!#7\rrD!P!!!,urrD!V!;HKq^]4?8q#:?`qu?]tec5.=!.`r,!rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;uisrq6-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_ +i;N`SrrDuj!!!,urrE&n!!!&srrD!V!;HKq^]4?8q#:?lqu?^%ec5.=!.`r,!- +!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrDui!;c]qJGB0F!W2lsi;N`Nrr^%:!!2lp!<2lr +!"[W[nG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uVrW)lr!;uKi!.XnG!5SC1!!2us!9!hV +p\t?2!!!&prrE&r!!!P[s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrDui!!#7\ +rrD!Q!!!&srrD!V!;HKq^]4?8p](-k!$BbknG`K=hZ*ZXs8E!!#Q42o!?^h1!!.Sbr;Zg^rr2uV +rW)lr!;uKi!$D+-!WW-!!=/Pp!!+22 +rVutK_#4655Q:Z_i;N`SrrDui!!!Q,rrDii!!!&srrD!V!;HKq^]4?8p\t6/r;ZhIec5.=!.`r, +!-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrDui!!!,urrE&o!!!&srrD!V +!;HKq^]4?8p\t6_rVup!eGo%-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_ +i;N`SrrE&j!;c]qJGK6G"8i)ui;N`Nrr^%:!!2io!;ufr!!h$RnG`K=hZ*ZXs8E!!#Q42o!?^h1 +!!.Sbr;Zg^rr2uVrW)lr!<2Tj!.XnG!5SF2!!E,u!9!hVp\t?2!!!&orrE&t!!!PZs7$$gJDU>- +!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`SrrE&j!!#7\rrD!R!!!,urrD!V!;HKq^]4?8pAY5F +!!#75s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#4655Q:Z_i;N`Rs7?9k+8c'rr@T,!!*-#rVus(r:Bsi+7T70!Iqo`!!#7_rrD!V!;lcr +JFrmB#Q+N$r;$Bn&,ZA,i;N`Nrr^%:!!2cm!J!D`s7$$gJDU>-!WW-!!=/Pp!!+22rVutK_#465 +5Q:Z_i;N`Rrr@TB!!!,urrE&p!!!Q,rrD!V!;HKq^]4?8`W,H-!.`r,!rr2unr;Zg.q>UH1rVup!qYpQRrW)]m"2Fm:!QG*.rr@T,!!+2"r;Zj_i:R'N+7T70!Iqo` +!!#7_rrD!V!;lcrrqufs5Q:Z_r;?Tq#PnB"i;N]V"8`#ti;N`Nrr^%:!!1(=nG`K=hZ*[A_#466 ++7Sq'!?^h1!!.Sbr;Zg^rr2uVrW)fpr;ZhIrr2utr;Zg"q>UHarVup'qYpQRrW)]m"2Fm:!QG*. +rr@T,!!,<7r;Zj/nFZb^+7T70!Iqo`!!#7_rrD!V!;c]qJGoQHs8;ot!Vu`qq#16n&,Q;+i;N`N +rr^%:!!1(=nG`K=hZ*Y+qu?a&q"4Uf+7T70!Iqo`!!#7_rrD!V!;c]t^]4?8r;QbIr;cZn!;ufr +!$D(;!9!hVp\t?2!!!&=s7$$gJDU>,J,B9I#Pdrl!?^h1!!.Sbr;Zg^rr2uVrW)fp"7Q9j#Q4T% +_#465J,0-D!!%NFrrD!V!;HKq^]4?8`W,H-!.`r,!<2lr!<`8m!!+22rVutK_#4655Q:Z_i;N`Q +rr`0!!$D.=!9!eU!'g;Z!l+d:q>UHQrW)]m"2Fm:!QG*.rr@T,!!*#r!!*3"o`,"7nGWCgJ&)!_ +!'gJ_!9!hVq>^Hp!.XqH!:]pe!$D%:!q60pq>UHQrW)]m"2Fm:!QG*.rr@T,!!)rp!!*,uo`,"7 +nGWCgJ&)!_!'gJ_!9!hVq>UKb#Q+N$q#(0m&,?/*!.XhE!9!hVp\t?2!!!&=s7$$gJDU>,r;6Nq +!W;Tj!?^h1!!.Sbr;Zg^rr2uVrW)Kg!;ucq!!hrl!9!hVp\t?2!!!&=s7$$gJD^D.!VlNl!<2Wk +!?^h1!!.Sbr;Zg^rr2uVrW)Kg!<2os!!DZh!9!hVp\t?2!!!&=s7$$gJD^D.!VlNl!<2Wk!?^h1 +!!.Sbr;Zg^rr2uVrW)Hfr;Zfumf*:FrW)]m"2Fm:!QG*.rr@T-!!*,qqZ$Wqo`,"7nGWCgJ&)!_ +!'gJ_!9!hVnG`K=r;c9c!9!hVp\t?2!!!&=s7$$gJD^D.!VlNl!<2Wk!?^h1!!.Sbr;Zg^rr2uV +rW)Hf!5SO5!.XJ;!9!hVp\t?2!!!&=s7$$gJD^D.!V#sd!.OS@!?^h1!!.Sbr;Zg^rr2uVrW)Hf +!9!eU!'frP!9!hVp\t?2!!!&=s7$$gJD^D."7Z0f!.OS@!?^h1!!.Sbr;Zg^rr2uVrW)Hf!:]pe +!$C\0!9!hVp\t?2!!!&=s7$$gJD^D."7Z0f!.XYA!?^h1!!.Sbr;Zg^rr2uVrW)co!Up?jrrDim +!!!Q*rrE+Lq>UHQrW)]m"2Fm:!QG*.rr@T-!!*2kqZ$VGo`,"7nGWCgJ&)!_!'gJ_!9!hVq>^Hp +!.XnG!;ucq!!iB#!q60pq>UHQrW)]m"2Fm:!QG*.rr@T-!!*2kqZ$VGo`,"7nGWCgJ&)!_!'gJ_ +!9!hVqYpZq!!",,r;6Nq!W;Tj!?^h1!!.Sbr;Zg^rr2uVrW)iq!9!eU!!E)tnc/YSqu6ZSrW)]m"2Fm: +!QG*.rr@T,!!)rp!!*,uo`,"7nGWCgJ&)!_!'gJ_!9!hVqu6Z3q#CC*rr2tKo)Jb4qu6ZSrW)]m +"2Fm:!QG*.rr@T,!!*#r!!*3"o`,"7nGWCgJ&)!_!'gJ_!9!hVqu6Z3q#CBsrr2u6o)Jb4qu6ZS +rW)]m"2Fm:!QG*.rr@T,!!%KG!!*2so`,"7nGWCgJ&)!_!'gJ_!9!hVqu6YHp]1,J,B9I#Pdrl!?^h1!!.Sbr;Zg^rr2uVrW)iq!.ahE"+U@NnFHV[ +&,ZA,i;N`Nrr^%:!!1(=nG`K=hZ*X@qu?a&nFZb^+7T70!Iqo`!!#7_rrD!V!;lfj!!>Ics7l0c +!!iE$!9!hVp\t?2!!!&=s7$$gJDU>-5Ci\4!>"\m!!,=RrVutK_#4655Q:Z_i;N`Rs7ZKq+92B= +o)Jaqqu6ZSrW)]m"2Fm:!QG*.rr@T,!!+1Wr;Zj?i:R'NJ+3F;!Iqo`!!#7_rrD!V!;uisrq?Bp +&-)\/o)Jamqu6ZSrW)]m"2Fm:!QG*.rr@T,!!+2"r;Zj__"@[.s7$!f!Iqo`!!#7_rrD!V!;uis +rq?Bm#QFbp!!!,urrD!V!;HKq^]4?8`W,H-!.`r,!>"\u!!.Sbp&G-ps7$!f!Iqo`!!#7_rrD!V +!;uisrq?Bm"9/<#JFigA"8i)ui;N`Nrr^%:!!1(=nG`K=hZ*Z^q#(0ns+'eC!X&JlrVutK_#465 +5Q:Z_i;N`SrrE&m!!!'!rrBk,!!!,urrD!V!;HKq^]4?8`W,H-!.`r,!<`9!!!*-#o`,$us5d`Z +^]4?Vr:L$j5QCZ^!Is&+!!#7_rrD!V!;uisr:U*m+92B=oDejlqu6ZSrW)]m"2Fm:!QG*.rr@T+ +!!RlA!!%NDo`,#BrquftJ)L8*!'gJ_!9!hVr;Qcpp&G1*s8W)j!!!&srrD!V!;HKq^]4?8`W,H- +!.`o+"X!XB!WV*N!!3,tr;ZkJ_#4655Q:Z_i;N`SrrDuj!!!9's7?9k!W2lsi;N`Nrr^%:!!1(= +nG`K=h>d]is1f`V_"Ia0!WVrn!!.Sbr;Zg^rr2uVrW)lr!;uNj!!E6#!.a_B!!2us!9!hVp\t6/ +rW'q;nG`K=h>dN\rVlkJp&G-rs7#se!Iqo`!!#7_rrD!V!;uisr:U*j!WN*!_"@[-!W2lsi;N`N +rrBk6!!%Mgs7$$gJDL8+!WN*!rq-6m#QN`\!!3,8r;Zg^rr2uVrW)lr!;uKirr2ufo`+smqu6ZS +rW)]m!5SR6!'eL'nG`K=h#RHS!;uKi!Y>=Hr;ZluJGfHJ5Q:Z_i;N`SrrE&k!!@`Ns8;Ni!!E,u +!9!hVp\t6/rVup?`rGQ.!.`l*"$chci:R'O+9-lj!!33$JGfHJ5Q:Z_i;N`SrrE&k!!#7YrrD!T +!!!,urrD!V!;HKn_#=<6&'"Y=rr@T*!!p!C-V_!!33$q"t*l5Q:Z_i;N`RrrD!U!!p!It+I!!39&q"t*l5Q:Z_i;N`RrrDQe!!Er;c]o!9!hV!.XbC +r;Zfua8bZ/!.`Aq!Wi>rr;Zm0s1nO4!'gJ_!9!hVqu6Zor;ZpAs8W)s!!!,rrrBk6!!!&rrrD!V +!!#7Xrr@TJ!6>-/rr@Sq!!39&nGN=g+9-lh!!#7_rrD!V!;lcrrqufs5Q:]]!!!&prrD!V!!!,t +rrD!V!!",8rrBk5!!%Mis7$$gJBn2s#QN`\!!,=aqZ$U\rr2uVrW)fpr;ZhIrr2tKr;cWm!:]sf +!!iB#!9!hV!"\i(!9!eU!'eR)nG`K=cN""Ws1nR5!It+G!!#7_rrD!V!;c]qJGoQIrrBk5!!%NE +rrDin!!!Q+rrD!V!!!8urrDQe!!"+^s7$$gJBn2s+9-li!!3,tqZ$U\rr2uVrW)fp"2Fm:!WE#u +i;EWU5PbrrDim!!!Q)rrTt9!Vu`qi;EZMrrE&s!!!,Bs7$$gJBn2rs8;fq!XJb`qZ$U\rr2uV +rW)corr<%KrVllqr;Zg&q#:Eb!!i?"!:]pe!.XbCr;ZfuaT(c0!.`Dr!Wi>rr;Zm0s1nL3!'gJ_ +!9!hVq>UKb#Q4T%rqufs"8Dfr!.XhE!:]pe!'g5X!.b"JaT(c0!.`Dr!X&Jlr;Zm@s+'tH!'gJ_ +!9!hVnc/Of!!2Ke!;QKm!$Ct8!5SO5!.W,jnG`K=ci=+Ps5^L[rr2uVrW)Kg!5SO5!.XG:!;ucq!!i8u +!:]pe!$B>_nG`K=ci=+hs+(%J!WW)o!!#7_rrD!V!:g'hi;EWU5OSOOrqufs"8Dfqq#(0m&'=k@ +rr@Sr!!,=ar;Zm"s7lEj!'gJ_!9!hVnc&UYr;Zg>mJm+b!!2io!;ucq!!gXGnG`K=ci=)rrqufu +"97le!!#7_rrD!V!:g'hq#(0m&+0AsJGfKBrrE&s!!!,Cs7$$gJC"8ss8;fq!XJb`q>^L[rr2uV +rW)Kg!;ucq!!hok!5SO5!.XbCr;ZfuaoCl1!.`Gs!Wi>rr;Zm0s1nI2!'gJ_!9!hVq>UKb#Q+N$ +rqufs"8Mls!.XeD!9!eU!'g5X!.b"JaoCl1!.`Gs!X&Jlr;Zm@s+'qG!'gJ_!9!hVq>^Hp!.XnG +r;Zfuq>UNc!!i=Hr;ZkJrqQNo5Q:Z_i;N`Qrr_`j +!!iE$!5SO5!.XkFrVuqJq>UHmr;Zg&p\t6_r;Zg>b5^u2!.`Gs![%Gmr;Zlur:pUHm +q>^L[qYpQbqZ$U\c2[;5!.`Jt![%Gmr;Zlur:g6l5Q:Z_i;N`RrrBk5!!!&srrD!U!!#7^rrDup +!!",:rrE&p!!!Q+rrDik!!!PSs7$$gJC4Du5QCZ^!Wi>rp](:Yrr2uVrW)iq!5SO5!!2us!:]pe +!$D1>!;u`p!$D"9q>^KtqYpQnqZ$Tuc2[;5!.`Jt!It+I!!39&nFut`5Q:Z_i;N`Rrr@TI!;lcr +q#(0m&,lM.q"t*l&,?/)JGT^9kc2[;5!.`Mu!Wi>rr;Zm0s1nC0!'gJ_!9!hVqu?Nn +!.XqH!<2os!!E3"!:]md!!i[!5SI3!'ed/nG`K=df9FSs5rr2uVqu?^!p]('i!!E)t!;u]o +!!COHnG`K=df9Durqufu"97lb!!#7_rrD!V!;uisr;-Ho+8c'^!!#7_rrD!V!;uisr;-Ho+8c'g?k!9!_ScN!D6!.`Q!!XJb@r;ZkJrq6pnG`K=e,TO\s+(%J!WW)k!!#7_rrD!V!;uis +r;-Ho+8Z!;i;EWX5QCc!qu?]tp\t6mq>^MFqYpQjqZ$VGciIcs1nO4!!2fnq>^MFqYpQnqZ$VGciCs1nO4!!2fn!.aqH!.XkF!;u]o!.W>pnG`K=e,TN!r;?Ts +#QN`U!!#7_rrD!V!;uisrqcZq5PkB[r;?Tt+92B!qu?^!pAY-.qZ$U\qYpQjqZ$U\ci[!;QEk!'eg0 +nG`K=eGoXOs7#se![%Gmp&G(Wrr2uVrW)lr!<2iq!'g;Zr;Zp1s8V$T!!!,prrDQc!!#7[rrDik +!!#70s7$$gJCOW$"97=Ho`+tVrr2uVrW)iq +!5SO5!!2lp!<2rt!tYG3r;6Np+85^7r;-HoJ,90Fr;-HoJ'\/arr@T#!!33$nGN=g+9-la!!#7_ +rrD!V!;lcri;EWU"8Mlrrr)m"&-)\/qu?^]pAY-jqZ$VGqYpQnqZ$VGcipnG`K= +ec5a^s+(%J!WW)i!!#7_rrD!V!;lcrr;?Tq+8Gj9rr)lt&,uS/_#=<6!VQHmrqc]krrE&q!7(W6 +rr@T#!!+2Ar;Zm"s7l3d!'gJ_!9!hVqu6Zqr;Zg^q#:?nrVup/rr2uVrVup#p&>$kqZ-Hl!<2iq +cN!D6!.`W#!C-S^!!39&nFQ\\5Q:Z_i;N`Qs8;otJ,'$Drr)lt&,uS/nGWCf#PA&o!!!&ps82is +!RC`7rr@T#!!.TIr;Zm(s5Er;Zg"cN!D6!.`Z$!Wi>jr;Zm@s+'_A!'gJ_!9!hV!.XnG"7Q9j#P\5urr)lt&,lP-!!%N@ +rr@TJ!!!,rrr@TJ!!!,Hs7$$gJCac&"97!'gJ_!9!hV!$D(;rr<%Kp\t6m +rVup/rVlrg!!i,q!9!eU!"\l)!9!eU!"[BTnG`K=f)Pj_s+(%J!WW)h!!#7_rrD!V!!!Q+rrMTo +pAY-lrVup/r;QctJ+N[?nGN=e+8Gj9nGN=e+3soUrr@T$!!+2Ar;Zm"s7#U[!'gJ_!9!hV!!hok +!<2rt!"\Gr!;QKm!'g8Y!;QKm!'ed/nG`K=f)Ph9rqufu"97<]r;Zluq!nCb5Q:Z_q#(0m&+9Gtrr)lt +&*s5srVurkrrW0"!6kK4rr@T%!!+2Ar;Zm"s7#RZ!'gJ_!;ucq!!hrl!<2rt!"\Ap!T4L\rrM$g +bl@24!.`]%!C-S^!!39&i:6jJ5Q:Z_rqufs"7H0hrr)lt&#B6prr@T%!!.TIr;Zm(s1n1*!'gG^ +r;Zfumf*:drVup/V#Tra!.`]%!WVrn!!3]2JFW[?5Q1T^JGfK9rrE&t!!!P*s7$$gJCso(!WVZf +!!+2AnGiPRrVll5r;ZhIn,ECerVup/V#Tra!.``&!X&J\r;Zj_rp]sg5Q1T^i;EWU5O\UPrr)lt +&#B6prr@T&!!3E*_#466J,Jg:!'gG^!:]pe!$C\0!<2rt!"Yn*nG`K=f`2'as+(%J!WVrb!!#7^ +rrDim!!!PurrE&t!!!P*s7$$gJCso'+929>!Wi>jnGiPRrVllqr;Zg&n,ECerVup/V#Tra!.``& +!C-S^!!39&i:-dI5Q1T^rqufs"7Q6irr)lt&#B6prr@T&!!.TIr;Zm(s1n.)!'gD]r;Zfun,ECe +rVup/V#Tra!.``&!WVrn!!3]2JFNU>5Q(N]JGfK:rrE&t!!!P*s7$$gJD'u)!WVZf!!+2An,NGQ +r;Qc4r;ZhInG`LfrVup/V#Tra!.`c'!X&J\r;Zj_rpTmf5Q(N]i;EWU5Oe[Qrr)lt&#B6prr@T' +!!3E*_#466J,Jd9!'gD]!:]pe!$C_1!<2rt!"Yn*nG`K=g&M0bs+(%J!WVra!!#7]rrDim!!!Q! +rrE&t!!!P*s7$$gJD'u(+929>!Wi>jn,NGQr;Qcpr;Zg&nG`LfrVup/V#Tra!.`c'!C-S^!!39& +i:$^H5Q(N]rqufs"7ZPqu6Z3r;ZhI +nc&UgrVup/V#Tra!.`f(!X&J\r;Zj_rpKge5PtH\i;EWU5OnaRrr)lt&#B6prr@T(!!3E*_#466 +J,Ja8!'gA\!:]pe!$Cb2!<2rt!"Yn*nG`K=gAh9cs+(%J!WVr`!!#7\rrDim!!!Q"rrE&t!!!P* +s7$$gJD1&)+929>!Wi>jmf3>Pqu6Zor;Zg&nc&UgrVup/V#Tra!.`f(!C-S^!!39&i9pXG5PtH\ +rqufs"7cBkrr)lt&#B6prr@T(!!.TIr;Zm(s1n('!'g>[r;Zfunc&UgrVup/V#Tra!.`f(!WVrn +!!3]2JF,+8u3>nGN=f+91a/!'g>[!5SO5!.XS>!<2rt +!"Yn*nG`K=hZ*X@rVllUr;Zj_rpBad5PkB[i;EWU5P"gSrr)lt&#B6prr@T,!!%NIrrBk5!!.TI +mJm5OqYpQbr;Zg>o)A^hrVup/V#Tra!.`r,r;QbIr;Zluq!J+^5PkB[q#(0m&+]`#rr)lt&#B6p +rr@T-!!!&ts8;p!!WVZW!!#7[rrDuq!!!8prrE&t!!!P*s7$$gJD^D-!WE#urqufu"97^Bn!!2Zj!<2rt!"Yn*nG`K=huEcY +nG*%c&-%1J!!#7Zrr@TJ!:p-irr)lt&#B6prr@T-!!*,iq#CF;s6Tdd5Pb^Qts7#CU!'g;Z!;ucq!!i,q!<2rt!"Yn*nG`K=huEcYnG3+d"97^O^O\rp0Ub5PY6Yi;EWU5P4sUrpToms7$$gJD^D.!V#pc!It%6!!#7YrrDQe!!",5rrE&f!!#6h +s7$$gJD^D.!V#pc!WVr]!!#7YrrDim!!!Q%rrE&f!!"+Hs7$$gJD^D.!V#sd!Wi>jli7#Mq#:?l +r;Zg&o`"pjn,NG!ZN'Fo!.`u-!$VrpKgeJ$]1Err@T-!!*,iqZ$X]r9F=_5PP0XnGN=e+8,X6rpKge5I:CZrr@T-!!*,iqZ$X] +q!.n[5PP0Xq#(0m&,#r&rpKge+1)":rr@T-!!*,iqZ$X]nEU&S5PP0Xr;?Tq#PJ)srpKge&$u<* +rr@T-!!*,iqZ$X]i9L@C5PP0Xrqufs"82ZorpKge#IFI"rr@T-!!*,iqZ$X]_!:t#5PG-U!!!&m +rrE&e!!!,-s7$$gJD^D.!V#sd!C),#!!#7Wrr@TJ!;6?lrpKge!OMgqrr@T-!!*2kqZ$U\l2UfK +pAY-.r;ZhIpAY-lmJsTnnG`K=huEc[nG<1c53`+J5PG*Wi;EWU5PG*WrpBadJ$f7Frr@T-!!*2k +qZ$U[l2UfKpAY-^r;Zg>p&FF[!'djjnG`K=huEc[nG<1c53`+J5PG*Wq#(0m&,#tj!!"+Js7$$g +JD^D."7Z0f!']ZJ!'g2W!;ucq!!i2s!.aM$V +JGfK@rrD!G!!!&,s7$$gJD^D."7Z0f!']ZJ!'g/V!5SO5!.X_B!:]CV[/]Xq!.`u-!<_ig!!#4J +!!#7VrrD!U!!#7WrrDi^!!%MVs7$$gJD^D."7Z0f!']ZJ!'g/V!:]pe!$Cq7!;u6b!'dmknG`K= +huEc[nG<1c53`+J5P>$Vq#(0m&,#tj!!"+Ks7$$gJD^D."7Z0f!']ZJ!'g/V!;ucq!!i2s!5S%' +!"ZL;nG`K=huEc[nG<1c53`+J5P>$Vrqufs"6][ar;?Tq#IXU$rr@T-!!*2kqZ$U[l2UfKo`+ji +!!29_!<2os!!BY/nG`K=huEc[nG<1c53`+J5P4sUJGfK1s8;ot!O_ssrr@T-!!*2kqZ$U[l2UfK +o`"p,r;ZhIkPkO4r;a8*nG`K=huEc[nG<1c53`+J5P4sUi;EWU5Ni%H_#465J%#CHrr@T-!!*2k +qZ$U[l2UfKo`"p\r;Zg>kPkP?r;Zg^[f>js!.`u-!<_ig!!#4J!!#7UrrDim!!!PmrrDQe!!"+L +s7$$gJD^D."7Z0f!']ZJ!'g,U!;ucq!!h]e!;QKm!"ZOkPkP?r;Zg^\,Yst +!.`u-!,"8i,_!!#7SrrD!U!!#7HrrBk5!!%MYs7$$gJA;-b5P"gSnGN=e ++6WY(i;EWU5Iga_rr@Sb!!#7SrrDim!!!PmrrDQe!!"+Ns7$$gJA;-b5P"gSr;?Tq#Nu*eq#(0m +&%MZ/rr@Sb!!#7SrrE&s!!!,arrDuq!!!86s7$$gJA;-b5OndP!!!&_rrE&s!!!,2s7$$gJA;-b +5OnaRJGfK1s8;ot!P&1!rr@Sb!!#7RrrBk5!!%N3rr@TJ!4`'urr@Sb!!#7RrrD!U!!#7HrrBk5 +!!%MZs7$$gJA;-b5OnaRnGN=e+6WY(i;EWU5Ipg`rr@Sb!!#7RrrDim!!!PmrrDQe!!"+Os7$$g +JA;-b5OnaRr;?Tq#Nu*eq#(0m&%V`0rr@Sb!!#7RrrE&s!!!,arrDuq!!!87s7$$gJA;-b5Oe^O +!!!&_rrE&s!!!,3s7$$gJA;-b5Oe[QJGfK1s8;ot!P/7"rr@Sb!!#7QrrBk5!!%N3rr@TJ!4i.! +rr@Sb!!#7QrrD!U!!#7HrrBk5!!%M[s7$$gJA;-b5Oe[QnGN=e+6WY(i;EWU5J$marr@Sb!!#7Q +rrDim!!!PmrrDQe!!"+Ps7$$gJA;-b5Oe[Qr;?Tq#Nu*eq#(0m&%_f1rr@Sb!!#7QrrE&s!!!,a +rrDuq!!!88s7$$gJA;-b5O\XN!!!&_rrE&s!!!,4s7$$gJA;-b5O\UPJGfK1s8;ot!P8=#rr@Sb +!!#7PrrBk5!!%N3rr@TJ!4r4"rr@Sb!!#7PrrD!U!!#7HrrBk5!!%M\s7$$gJA;-b5O\UPnGN=e ++6WY(i;EWU5J-sbrr@Sb!!#7PrrDim!!!PmrrDQe!!"+Qs7$$gJA;-b5O\UPr;?Tq#Nu*eq#(0m +&%hl2rr@Sb!!#7PrrE&s!!!,arrDuq!!!89s7$$gJA;-b5OSRM!!!&_rrE&s!!!,5s7$$gJA;-b +5OSOOJGfK1s8;ot!PAC$rr@Sb!!#7OrrBk5!!%N3rr@TJ!5&:#rr@Sb!!#7OrrD!U!!#7HrrBk5 +!!%M]s7$$gJA;-b5OSOOnGN=e+6WY(i;EWU5J7$crr@Sb!!#7OrrDim!!!PmrrDQe!!"+Rs7$$g +JA;-b5OSOOr;?Tq#Nu*eq#(0m&%qr3rr@Sb!!#7OrrE&s!!!,arrDuq!!!8:s7$$gJA;-b5OJLL +!!!&_rrE&s!!!,6s7$$gJA;-b5OJINJGfK1s8;ot!PJI%rr@Sb!!#7NrrBk5!!%N3rr@TJ!5/@$ +rr@Sb!!#7NrrD!U!!#7HrrBk5!!%M^s7$$gJA;-b5OJINnGN=e+6WY(i;EWU5J@*drr@Sb!!#7N +rrDim!!!PmrrDQe!!"+Ss7$$gJA;-b5OJINr;?Tq#Nu*eq#(0m&&rr@Sb!!#7NrrE&s!!!,a +rrDuq!!!8;s7$$gJA;-b5OAFK!!!&_rrE&s!!!,7s7$$gJA;-b5OACMJGfK1s8;ot!PSO&rr@Sb +!!#7MrrBk5!!%N3rr@TJ!58F%rr@Sb!!#7MrrD!U!!#7HrrBk5!!%M_s7$$gJA;-b5OACMnFln_ +#OVNki;EWU5JI0err@Sb!!#7MrrDig!!!8krrDQe!!*o=^]3g'!._ib!'fiM!;uQk!!hok!;QEk +!'e:!nG`K=^]4@!m/I(bpAb0umJd1aqZ$U,_#Np(!._ib!'ffLpAb0umJd1cqZ$Tu_#Np(!._ib +!'ffL!.ahE!!hljq>e>2nG`K=^]4@!li-t#p](:!m/I'9qZ$VG_>j$)!._ib!'ffL!9!VP!!hlj +!5SI3!'e="nG`K=^]4@!li-tSp](:!m/I(DqZ$U<_>j$)!._ib!'ffL!;Qj$)!._ib!'ffL!<2`n!!hlj!;u]o!!C(;nG`K=^]4@! +lMpVZ!!hlj!<2iq!!0q9nG`K=^]4@!lMgj7q#CC"li6e]_>j$)!._ib!'fcK!5SC1!!hii!.aqH +_>j$)!._ib!'fcK!9!YQ!!hii!5SI3!.VlcnG`K=^]4@!lMgkRq#CC"li-tCqZ$VG_Z0-*!._ib +!'fcK!;Q?i!!hii!:]jc!'e@#nG`K=^]4@!lMgk^q#CC"li-t[qZ$U\_Z0-*!._ib!'fcK!<2co +!!hii!;u]o!$B)XnG`K=^]4@!l2UPZ!!hii!<2iq!$B)XnG`K=^]4@!l2La6q>^L#lMp_]!$B)X +nG`K=^]4@!l2Lb!q>^L#lMp_]!$B)XnG`K=^]4@!l2LbAq>^L#li-taqZ$U,_Z0-*!._ib!'f`J +!:]gb!!hii!<2iq!"ZsHnG`K=^]4@!l2LbYq>^L#li-taqZ$U,_Z0-*!._ib!'f`J!;uZn!!hii +!<2iq!"ZsHnG`K=^]4@!l2Lb_q>^L#li-taqZ$U,_Z0-*!._ib!'f]Iq>^L#li-taqZ$U,_Z0-* +!._ib!'f]I!.aqH!!hii!<2iq!"ZsHnG`K=^]4@!kl1XuqZ$U$li-taqZ$U,_Z0-*!._ib!'f]I +!9!_S!!hii!<2iq!"ZsHnG`K=^]4@!kl1YPqZ$U$lMp_]!$B)XnG`K=^]4@!kl1YXqZ$U$lMp_] +!$B)XnG`K=^]4@!kl1Y\qZ$U$lMp_]!$B)XnG`K=^]4@!kl1Y^qZ$U$lMp_]!$B)XnG`K=^]4@! +kl1Y^qZ$U$lMgj7qu?^]_Z0-*!._ib!'f]I!<2iq!!hfh!.atI!'e@#nG`K=^]4@!kl1Y^qZ$U$ +lMgk"qu?_H_Z0-*!._ib!'f]I!<2iq!!hfh!5SL4!.VlcnG`K=^]4@!kl1Y^qZ$U$lMgkBquFS5 +nG`K=^]4@!kl1Y^qZ$U$lMgkBquFS5nG`K=^]4@!kl1Y^qZ$U$lMgkRr;Zfu_>j$)!._ib!'f]I +!<2iq!!hfh!;QKm!!C(;nG`K=^]4@!kl1Y^qZ$U$lMgk^r;Zg&_>j$)!._ib!'f]I!<2iq!!hfh +!<2os!"ZpGnG`K=^]4@!kl1Y^qZ$U$l2U\^!$B&WnG`K=^]4@!kl1Y^qZ$U$l2La6rVup__>j$) +!._ib!'f]I!<2iq!!hcg!5SR6!.VibnG`K=^]4@!kl1Y^qZ$U$l2LbArW'b6nG`K=^]4@!kl1Y^ +qZ$U$l2Lk\!!!,:s7$$gJA;-b5Nr+IrqcZq#O26jrVup/_#Np(!._ib!'f]I!<2iq!!h`f!e:88 +_#Np(!._ib!'f]I!<2iq!!h`f!Vcc3s7$$gJA;-b5D/ues0)HRs0)HRs0)HRs0)HRs0)HRs0)HR +s0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HR +s0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HR +s0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HR +s0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HR +s0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HRs0)HQ~> +%%EndData +showpage +%%Trailer +end +%%EOF Index: tags/1.2.7/doc-orig/gcode_control_img.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode_control_img.pdf =================================================================== --- tags/1.2.7/doc-orig/gcode_control_img.pdf (nonexistent) +++ tags/1.2.7/doc-orig/gcode_control_img.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode_control_img.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode_control_img.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode_control_img.png =================================================================== --- tags/1.2.7/doc-orig/gcode_control_img.png (nonexistent) +++ tags/1.2.7/doc-orig/gcode_control_img.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode_control_img.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode_tool_path.eps =================================================================== --- tags/1.2.7/doc-orig/gcode_tool_path.eps (nonexistent) +++ tags/1.2.7/doc-orig/gcode_tool_path.eps (revision 13657) @@ -0,0 +1,415 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: cairo 1.8.10 (http://cairographics.org) +%%CreationDate: Mon May 30 02:27:10 2011 +%%Pages: 1 +%%BoundingBox: 0 0 403 230 +%%DocumentData: Clean7Bit +%%LanguageLevel: 2 +%%EndComments +%%BeginProlog +/cairo_eps_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +/q { gsave } bind def +/Q { grestore } bind def +/cm { 6 array astore concat } bind def +/w { setlinewidth } bind def +/J { setlinecap } bind def +/j { setlinejoin } bind def +/M { setmiterlimit } bind def +/d { setdash } bind def +/m { moveto } bind def +/l { lineto } bind def +/c { curveto } bind def +/h { closepath } bind def +/re { exch dup neg 3 1 roll 5 3 roll moveto 0 rlineto + 0 exch rlineto 0 rlineto closepath } bind def +/S { stroke } bind def +/f { fill } bind def +/f* { eofill } bind def +/B { fill stroke } bind def +/B* { eofill stroke } bind def +/n { newpath } bind def +/W { clip } bind def +/W* { eoclip } bind def +/BT { } bind def +/ET { } bind def +/pdfmark where { pop globaldict /?pdfmark /exec load put } + { globaldict begin /?pdfmark /pop load def /pdfmark + /cleartomark load def end } ifelse +/BDC { mark 3 1 roll /BDC pdfmark } bind def +/EMC { mark /EMC pdfmark } bind def +/cairo_store_point { /cairo_point_y exch def /cairo_point_x exch def } def +/Tj { show currentpoint cairo_store_point } bind def +/TJ { + { + dup + type /stringtype eq + { show } { -0.001 mul 0 cairo_font_matrix dtransform rmoveto } ifelse + } forall + currentpoint cairo_store_point +} bind def +/cairo_selectfont { cairo_font_matrix aload pop pop pop 0 0 6 array astore + cairo_font exch selectfont cairo_point_x cairo_point_y moveto } bind def +/Tf { pop /cairo_font exch def /cairo_font_matrix where + { pop cairo_selectfont } if } bind def +/Td { matrix translate cairo_font_matrix matrix concatmatrix dup + /cairo_font_matrix exch def dup 4 get exch 5 get cairo_store_point + /cairo_font where { pop cairo_selectfont } if } bind def +/Tm { 2 copy 8 2 roll 6 array astore /cairo_font_matrix exch def + cairo_store_point /cairo_font where { pop cairo_selectfont } if } bind def +/g { setgray } bind def +/rg { setrgbcolor } bind def +/d1 { setcachedevice } bind def +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +%%PageBoundingBox: 0 0 403 230 +%%EndPageSetup +q +1 g +0 0 403 230 rectfill +1 0 0 rg +0.5 w +0 J +0 j +[] 0.0 d +10 M q 1 0 0 1 0 230 cm +0 -230.398 m 32.879 -14.398 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +32.879 -14.398 m 32.879 -211.922 l 159.84 -211.922 l 159.84 -70.559 l +150.238 -70.559 l 148.32 -71.762 l 148.32 -72.238 l 150.238 -73.441 l +152.16 -76.32 l 152.641 -79.441 l 152.16 -81.84 l 150.961 -84 l 150.238 +-84.48 l 150.238 -142.801 l 149.762 -144.238 l 149.039 -145.922 l +114.961 -179.281 l 114.961 -186.238 l 114 -186.961 l 100.559 -186.961 l +99.602 -186 l 99.602 -172.559 l 100.559 -171.359 l 107.52 -171.359 l +138.961 -139.441 l 138.961 -84.48 l 138 -83.281 l 137.281 -81.84 l +136.801 -79.199 l 137.281 -76.559 l 138.238 -74.641 l 139.922 -72.961 l +141.121 -72 l 139.922 -71.039 l 138.238 -69.359 l 137.281 -67.441 l +136.801 -64.801 l 137.281 -62.16 l 138.238 -60.238 l 140.398 -58.078 l +137.762 -58.078 l 137.52 -57.602 l 121.922 -57.602 l 112.801 -66.238 l +112.801 -130.801 l 113.52 -131.281 l 114.719 -133.441 l 115.199 +-136.078 l 114.719 -138.961 l 112.801 -141.84 l 110.641 -143.281 l +109.441 -143.762 l 106.801 -144 l 104.16 -143.52 l 101.52 -141.602 l +100.078 -139.441 l 99.602 -137.52 l 99.602 -134.641 l 100.078 -132.719 +l 101.52 -130.801 l 101.52 -63.84 l 102.48 -60.719 l 116.16 -47.281 l +118.078 -46.32 l 137.039 -46.078 l 137.039 -43.441 l 138.238 -42.48 l +151.441 -42.48 l 152.398 -43.68 l 152.398 -57.359 l 151.441 -58.078 l +149.281 -58.078 l 149.281 -58.559 l 149.762 -59.039 l 157.68 -59.039 l +158.398 -58.32 l 158.398 -38.641 l 159.359 -35.52 l 159.84 -35.281 l +159.84 -14.398 l 32.879 -14.398 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +32.879 -14.398 m 46.078 -50.16 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +46.078 -50.16 m 43.441 -50.879 l 41.281 -51.84 l 38.16 -54 l 36 -56.641 +l 34.32 -60 l 33.602 -64.801 l 34.32 -69.602 l 36 -72.961 l 38.16 +-75.602 l 41.281 -77.762 l 43.441 -78.719 l 46.32 -79.441 l 50.16 +-79.441 l 53.039 -78.719 l 55.68 -77.52 l 58.559 -75.359 l 60.238 +-73.199 l 62.16 -69.602 l 62.879 -65.281 l 62.641 -62.641 l 62.16 -60 l +60.238 -56.398 l 58.559 -54.238 l 55.68 -52.078 l 53.039 -50.879 l +50.16 -50.16 l 46.078 -50.16 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +46.078 -50.16 m 217.922 -16.801 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +217.922 -16.801 m 217.199 -17.281 l 208.801 -25.441 l 208.078 -26.879 l +208.078 -49.199 l 205.441 -52.078 l 197.281 -52.078 l 195.84 -50.398 l +193.922 -49.441 l 190.32 -49.441 l 188.398 -50.398 l 186.719 -52.32 l +186 -53.762 l 186 -57.359 l 186.719 -58.801 l 188.398 -60.719 l 190.32 +-61.68 l 193.922 -61.68 l 195.84 -60.719 l 197.281 -59.039 l 207.121 +-59.039 l 208.559 -58.32 l 214.559 -52.078 l 215.039 -51.121 l 215.039 +-28.801 l 219.84 -23.762 l 263.039 -23.762 l 277.922 -38.879 l 277.922 +-46.801 l 290.879 -46.801 l 290.879 -33.84 l 282.238 -33.84 l 266.16 +-17.52 l 264.719 -16.801 l 217.922 -16.801 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +217.922 -16.801 m 332.879 -34.078 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +332.879 -34.078 m 331.68 -34.559 l 330.238 -35.281 l 328.559 -37.199 l +327.84 -38.641 l 327.84 -42 l 328.559 -43.922 l 302.641 -70.078 l +264.238 -70.078 l 263.281 -70.559 l 259.199 -74.398 l 258.48 -75.84 l +258.48 -85.441 l 249.121 -94.559 l 239.762 -94.559 l 239.039 -93.602 l +237.121 -92.641 l 233.52 -92.641 l 231.602 -93.602 l 229.922 -95.52 l +229.199 -96.961 l 229.199 -100.559 l 229.922 -102 l 231.602 -103.922 l +233.52 -104.879 l 237.121 -104.879 l 239.039 -103.922 l 241.199 -101.52 +l 251.039 -101.52 l 252 -101.039 l 264.719 -88.559 l 265.441 -87.121 l +265.441 -77.52 l 265.922 -77.039 l 304.32 -77.039 l 305.762 -76.32 l +335.039 -46.801 l 337.199 -45.84 l 339.121 -44.16 l 340.078 -42.238 l +340.078 -38.641 l 339.359 -37.199 l 337.68 -35.281 l 335.762 -34.32 l +332.879 -34.078 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +332.879 -34.078 m 228.961 -34.559 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +228.961 -34.559 m 228.961 -47.52 l 241.922 -47.52 l 241.922 -34.559 l +228.961 -34.559 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +228.961 -34.559 m 191.039 -34.801 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -34.801 m 189.359 -35.52 l 163.199 -35.52 l 161.762 -36.719 l +160.559 -38.16 l 160.559 -59.52 l 158.398 -61.441 l 149.762 -61.441 l +148.32 -59.762 l 146.398 -58.801 l 142.801 -58.801 l 141.359 -59.52 l +139.441 -61.199 l 138.48 -63.121 l 138.48 -66.719 l 139.441 -68.641 l +141.359 -70.32 l 142.801 -71.039 l 146.398 -71.039 l 148.32 -70.078 l +149.762 -68.398 l 160.32 -68.398 l 161.281 -67.922 l 166.801 -62.641 l +167.52 -61.199 l 167.52 -42.48 l 186 -42.48 l 186.48 -44.16 l 188.398 +-46.32 l 190.32 -47.281 l 193.922 -47.281 l 195.84 -46.32 l 197.52 +-44.398 l 198.238 -42.961 l 198.238 -39.359 l 197.52 -37.922 l 195.84 +-36 l 193.922 -35.039 l 191.039 -34.801 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -34.801 m 138.238 -43.922 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +138.238 -43.922 m 138.238 -48.48 l 118.801 -48.48 l 117.84 -48.961 l +104.398 -62.16 l 103.68 -63.602 l 103.68 -131.039 l 102 -132.48 l +101.039 -134.398 l 101.039 -138 l 101.762 -139.441 l 103.441 -141.359 l +105.359 -142.32 l 108.961 -142.32 l 110.879 -141.359 l 112.559 -139.441 +l 113.281 -138 l 113.281 -134.398 l 112.32 -132.48 l 110.641 -131.039 l +110.641 -65.52 l 120.48 -55.441 l 138.238 -55.441 l 138.238 -56.879 l +151.199 -56.879 l 151.199 -43.922 l 138.238 -43.922 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +138.238 -43.922 m 234.238 -49.199 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +234.238 -49.199 m 233.039 -49.68 l 231.602 -50.398 l 229.922 -52.32 l +229.199 -53.762 l 229.199 -57.359 l 230.16 -59.281 l 232.078 -60.961 l +233.52 -61.68 l 237.121 -61.68 l 239.039 -60.719 l 240.719 -58.801 l +241.441 -57.359 l 241.441 -53.762 l 240.719 -52.32 l 239.039 -50.398 l +237.121 -49.441 l 234.238 -49.199 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +234.238 -49.199 m 191.039 -63.602 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -63.602 m 189.84 -64.078 l 188.398 -64.801 l 186.719 -66.719 l +186 -68.16 l 186 -71.762 l 186.961 -73.68 l 188.879 -75.359 l 190.32 +-76.078 l 193.922 -76.078 l 195.84 -75.121 l 197.52 -73.199 l 198.238 +-71.762 l 198.238 -68.16 l 197.52 -66.719 l 195.84 -64.801 l 193.922 +-63.84 l 191.039 -63.602 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -63.602 m 234.238 -63.602 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +234.238 -63.602 m 233.039 -64.078 l 231.602 -64.801 l 230.16 -66.48 l +216 -66.48 l 215.039 -66.961 l 208.801 -72.961 l 208.078 -74.398 l +208.078 -90.961 l 204.719 -94.559 l 196.559 -94.559 l 195.84 -93.602 l +193.922 -92.641 l 190.32 -92.641 l 188.879 -93.359 l 186.961 -95.039 l +186 -96.961 l 186 -100.559 l 186.961 -102.48 l 188.879 -104.16 l 190.32 +-104.879 l 193.922 -104.879 l 195.84 -103.922 l 198 -101.52 l 206.398 +-101.52 l 207.84 -100.801 l 214.559 -93.84 l 215.039 -92.879 l 215.039 +-76.078 l 217.922 -73.441 l 230.16 -73.441 l 231.602 -75.121 l 233.52 +-76.078 l 237.121 -76.078 l 239.039 -75.121 l 240.719 -73.199 l 241.441 +-71.762 l 241.441 -68.16 l 240.719 -66.719 l 239.039 -64.801 l 237.121 +-63.84 l 234.238 -63.602 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +234.238 -63.602 m 143.52 -72.961 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +143.52 -72.961 m 142.32 -73.441 l 140.879 -74.16 l 139.199 -76.078 l +138.48 -77.52 l 138.48 -81.121 l 139.441 -83.039 l 141.121 -84.48 l +141.121 -140.879 l 108.961 -172.801 l 100.801 -172.801 l 100.801 +-185.762 l 113.762 -185.762 l 113.762 -177.359 l 147.359 -144 l 148.078 +-142.559 l 148.078 -84.48 l 149.762 -83.039 l 150.719 -81.121 l 150.719 +-77.52 l 150 -76.078 l 148.32 -74.16 l 146.398 -73.199 l 143.52 -72.961 +l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +143.52 -72.961 m 191.039 -78 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -78 m 189.84 -78.48 l 188.398 -79.199 l 186.48 -81.359 l 186 +-83.039 l 174.961 -83.039 l 174 -83.52 l 168.48 -88.801 l 167.762 +-90.238 l 167.762 -163.441 l 168.48 -164.879 l 210.961 -207.121 l +210.961 -211.68 l 223.922 -211.68 l 223.922 -198.719 l 211.68 -198.719 +l 174.719 -161.52 l 174.719 -92.16 l 176.641 -90 l 189.359 -90 l +191.281 -90.719 l 193.922 -90.48 l 195.84 -89.52 l 197.52 -87.602 l +198.238 -86.16 l 198.238 -82.559 l 197.52 -81.121 l 195.84 -79.199 l +193.922 -78.238 l 191.039 -78 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -78 m 234.238 -78 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +234.238 -78 m 233.039 -78.48 l 231.602 -79.199 l 229.922 -81.121 l +229.199 -82.559 l 229.199 -86.16 l 230.16 -88.078 l 232.078 -89.762 l +233.52 -90.48 l 237.121 -90.48 l 239.039 -89.52 l 240.719 -87.602 l +241.441 -86.16 l 241.441 -82.559 l 240.719 -81.121 l 239.039 -79.199 l +237.121 -78.238 l 234.238 -78 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +234.238 -78 m 283.199 -91.68 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +283.199 -91.68 m 282 -92.16 l 280.559 -92.879 l 278.879 -94.801 l +278.16 -96.238 l 278.16 -99.84 l 279.121 -101.762 l 280.801 -103.199 l +280.801 -144 l 281.281 -144.961 l 293.039 -156.961 l 293.281 -160.32 l +294.238 -162.238 l 296.16 -163.922 l 297.602 -164.641 l 301.199 +-164.641 l 303.121 -163.68 l 304.801 -161.762 l 305.52 -160.32 l 305.52 +-156.719 l 304.801 -155.281 l 303.121 -153.359 l 301.199 -152.398 l +297.84 -152.16 l 287.762 -142.32 l 287.762 -103.199 l 289.68 -101.52 l +305.52 -101.52 l 308.879 -105.121 l 308.879 -118.801 l 307.199 -120.238 +l 306.238 -122.16 l 306.238 -125.762 l 306.961 -127.199 l 308.641 +-129.121 l 310.559 -130.078 l 314.16 -130.078 l 316.078 -129.121 l +317.762 -127.199 l 318.48 -125.762 l 318.48 -122.16 l 317.52 -120.238 l +315.84 -118.801 l 315.84 -103.199 l 315.121 -101.762 l 308.16 -95.039 l +307.199 -94.559 l 289.441 -94.559 l 288 -92.879 l 286.078 -91.922 l +283.199 -91.68 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +283.199 -91.68 m 191.039 -106.801 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -106.801 m 189.84 -107.281 l 188.398 -108 l 186.719 -109.922 l +186 -111.359 l 186 -114.961 l 186.961 -116.879 l 188.879 -118.559 l +190.32 -119.281 l 193.922 -119.281 l 195.84 -118.32 l 197.281 -116.641 +l 212.641 -116.641 l 226.078 -130.32 l 227.52 -131.039 l 230.16 +-131.039 l 231.602 -132.719 l 233.52 -133.68 l 237.121 -133.68 l +238.559 -132.961 l 240.48 -131.281 l 241.441 -129.359 l 241.441 +-125.762 l 240.48 -123.84 l 238.559 -122.16 l 237.121 -121.441 l 233.52 +-121.441 l 231.602 -122.398 l 230.16 -124.078 l 229.199 -124.078 l +215.039 -109.68 l 213.602 -108.961 l 212.16 -108.961 l 211.199 -109.68 +l 197.281 -109.68 l 195.84 -108 l 193.922 -107.039 l 191.039 -106.801 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -106.801 m 234.238 -106.801 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +234.238 -106.801 m 233.039 -107.281 l 231.602 -108 l 229.922 -109.922 l +229.199 -111.359 l 229.199 -114.961 l 230.16 -116.879 l 232.078 +-118.559 l 233.52 -119.281 l 237.121 -119.281 l 239.039 -118.32 l +239.762 -117.359 l 253.68 -117.359 l 254.16 -117.84 l 254.16 -147.602 l +254.641 -148.559 l 264.238 -158.398 l 264.48 -160.32 l 265.199 -161.762 +l 266.879 -163.68 l 268.801 -164.641 l 272.398 -164.641 l 274.32 +-163.68 l 276 -161.762 l 276.719 -160.32 l 276.719 -156.719 l 276 +-155.281 l 274.32 -153.359 l 272.398 -152.398 l 270.238 -152.16 l +268.078 -152.641 l 261.121 -145.922 l 261.121 -116.16 l 260.398 +-114.719 l 256.32 -110.879 l 255.359 -110.398 l 241.199 -110.398 l +239.039 -108 l 237.121 -107.039 l 234.238 -106.801 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +234.238 -106.801 m 191.039 -121.199 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -121.199 m 189.84 -121.68 l 188.398 -122.398 l 186.719 -124.32 +l 186 -125.762 l 186 -129.359 l 186.961 -131.281 l 188.879 -132.961 l +190.32 -133.68 l 193.922 -133.68 l 195.84 -132.719 l 197.281 -131.039 l +204 -131.039 l 215.281 -142.559 l 216.719 -143.281 l 229.199 -143.281 l +229.68 -144.961 l 231.602 -147.121 l 233.52 -148.078 l 237.121 -148.078 +l 238.559 -147.359 l 240.48 -145.68 l 241.441 -143.762 l 241.441 +-140.16 l 240.48 -138.238 l 238.559 -136.559 l 237.121 -135.84 l 234.48 +-135.602 l 232.559 -136.32 l 218.398 -136.32 l 207.121 -124.801 l +205.68 -124.078 l 197.281 -124.078 l 195.84 -122.398 l 193.922 -121.441 +l 191.039 -121.199 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -121.199 m 191.039 -135.602 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -135.602 m 189.84 -136.078 l 188.398 -136.801 l 186.719 +-138.719 l 186 -140.16 l 186 -143.762 l 186.961 -145.68 l 188.879 +-147.359 l 190.32 -148.078 l 193.922 -148.078 l 195.84 -147.121 l +197.281 -145.441 l 202.32 -145.441 l 216.719 -159.602 l 216.719 -179.52 +l 217.922 -180.961 l 219.359 -182.16 l 247.199 -182.16 l 268.559 +-203.762 l 268.801 -207.121 l 269.52 -208.559 l 271.199 -210.48 l +273.121 -211.441 l 276.719 -211.441 l 278.641 -210.48 l 280.32 -208.559 +l 281.039 -207.121 l 281.039 -203.52 l 280.32 -202.078 l 278.641 +-200.16 l 276.719 -199.199 l 273.359 -198.961 l 249.84 -175.68 l +248.879 -175.199 l 223.68 -175.199 l 223.68 -157.922 l 223.199 -156.961 +l 205.68 -139.199 l 204.238 -138.48 l 197.281 -138.48 l 195.84 -136.801 +l 193.922 -135.84 l 191.039 -135.602 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -135.602 m 191.039 -150 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +191.039 -150 m 189.84 -150.48 l 188.398 -151.199 l 186.719 -153.121 l +186 -154.559 l 186 -158.16 l 186.961 -160.078 l 188.879 -161.762 l +190.32 -162.48 l 193.922 -162.48 l 195.84 -161.52 l 197.52 -159.602 l +198.238 -158.16 l 198.238 -154.559 l 197.52 -153.121 l 195.84 -151.199 +l 193.922 -150.238 l 191.039 -150 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +191.039 -150 m 234.238 -150 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +234.238 -150 m 233.039 -150.48 l 231.602 -151.199 l 229.922 -153.121 l +229.199 -154.559 l 229.199 -158.16 l 230.16 -160.078 l 232.078 -161.762 +l 233.52 -162.48 l 237.121 -162.48 l 239.039 -161.52 l 240.719 -159.602 +l 241.441 -158.16 l 241.441 -154.559 l 240.719 -153.121 l 239.039 +-151.199 l 237.121 -150.238 l 234.238 -150 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +234.238 -150 m 46.559 -51.84 l S Q +0 g +0.5 w +q 1 0 0 1 0 230 cm +46.559 -51.84 m 44.641 -52.32 l 42.238 -53.281 l 39.602 -54.961 l +37.441 -57.359 l 36 -60 l 35.281 -62.398 l 35.281 -67.441 l 36 -69.84 l +37.441 -72.48 l 39.602 -74.879 l 42.238 -76.559 l 45.359 -77.762 l +50.879 -77.762 l 54 -76.559 l 56.641 -74.879 l 58.801 -72.48 l 60.238 +-69.84 l 60.961 -67.441 l 60.961 -62.398 l 60.238 -60 l 58.801 -57.359 +l 56.641 -54.961 l 54 -53.281 l 50.879 -52.078 l 46.559 -51.84 l S Q +1 0 0 rg +0.5 w +q 1 0 0 1 0 230 cm +46.559 -51.84 m S Q +Q +showpage +%%Trailer +count op_count sub {pop} repeat +countdictstack dict_count sub {end} repeat +cairo_eps_state restore +%%EOF Index: tags/1.2.7/doc-orig/gcode_tool_path.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode_tool_path.pdf =================================================================== --- tags/1.2.7/doc-orig/gcode_tool_path.pdf (nonexistent) +++ tags/1.2.7/doc-orig/gcode_tool_path.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode_tool_path.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/gcode_tool_path.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/gcode_tool_path.png =================================================================== --- tags/1.2.7/doc-orig/gcode_tool_path.png (nonexistent) +++ tags/1.2.7/doc-orig/gcode_tool_path.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/gcode_tool_path.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/new_gen/Makefile =================================================================== --- tags/1.2.7/doc-orig/new_gen/Makefile (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/Makefile (revision 13657) @@ -0,0 +1,14 @@ +all: fractional_size.html letter_size.html metric_size.html wire_size.html + +fractional_size.html: fractional_size.tab tab2html.sh + ./tab2html.sh 4 < fractional_size.tab >$@ + +letter_size.html: letter_size.tab tab2html.sh + ./tab2html.sh 4 < letter_size.tab >$@ + +metric_size.html: metric_size.tab tab2html.sh + ./tab2html.sh 4 < metric_size.tab >$@ + +wire_size.html: wire_size.tab tab2html.sh + ./tab2html.sh 4 < wire_size.tab >$@ + Index: tags/1.2.7/doc-orig/new_gen/README =================================================================== --- tags/1.2.7/doc-orig/new_gen/README (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/README (revision 13657) @@ -0,0 +1,2 @@ +New scripts to generate html using old doc input files. This directory +will be merged in the main doc eventually. Index: tags/1.2.7/doc-orig/new_gen/fractional_size.tab =================================================================== --- tags/1.2.7/doc-orig/new_gen/fractional_size.tab (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/fractional_size.tab (revision 13657) @@ -0,0 +1,65 @@ +@Drill
            Size Diameter
            (inches) +1/64 .0156 +1/32 .0313 +3/64 .0469 +1/16 .0625 +5/64 .0781 +3/32 .0938 +7/64 .1094 +1/8 .1250 +9/64 .1406 +5/32 .1562 +11/64 .1719 +3/16 .1875 +13/64 .2031 +7/32 .2188 +15/64 .2344 +1/4 .2500 +17/64 .2656 +9/32 .2812 +19/64 .2969 +5/16 .3125 +21/64 .3281 +11/32 .3438 +23/64 .3594 +3/8 .3750 +25/64 .3906 +13/32 .4062 +27/64 .4219 +7/16 .4375 +29/64 .4531 +15/32 .4688 +31/64 .4844 +1/2 .5000 +33/64 .5156 +17/32 .5313 +35/64 .5469 +9/16 .5625 +37/64 .5781 +19/32 .5938 +39/64 .6094 +5/8 .6250 +41/64 .6406 +21/32 .6562 +43/64 .6719 +11/16 .6875 +45/64 .7031 +23/32 .7188 +47/64 .7344 +3/4 .7500 +49/64 .7656 +25/32 .7812 +51/64 .7969 +13/16 .8125 +53/64 .8281 +27/32 .8438 +55/64 .8594 +7/8 .8750 +57/64 .8906 +29/32 .9062 +59/64 .9219 +15/16 .9375 +61/64 .9531 +31/32 .9688 +63/64 .9844 +1 1.0000 Index: tags/1.2.7/doc-orig/new_gen/letter_size.tab =================================================================== --- tags/1.2.7/doc-orig/new_gen/letter_size.tab (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/letter_size.tab (revision 13657) @@ -0,0 +1,28 @@ +@Drill
            Size Diameter
            (inches) +A .2340 +B .2380 +C .2420 +D .2460 +E .2500 +F .2570 +G .2610 +H .2660 +I .2720 +J .2770 +K .2810 +L .2900 +M .2950 +N .3020 +O .3160 +P .3230 +Q .3320 +R .3390 +S .3480 +T .3580 +U .3680 +V .3770 +W .3860 +X .3970 +Y .4040 +Z .4130 + Index: tags/1.2.7/doc-orig/new_gen/metric_size.tab =================================================================== --- tags/1.2.7/doc-orig/new_gen/metric_size.tab (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/metric_size.tab (revision 13657) @@ -0,0 +1,190 @@ +@Drill
            Size Diameter
            (inches) +0.20 mm .00787 +0.25 mm .00984 +0.30 mm .0118 +0.35 mm .0138 +0.40 mm .0158 +0.45 mm .0177 +0.50 mm .0197 +0.55 mm .0217 +0.60 mm .0236 +0.65 mm .0256 +0.70 mm .0276 +0.75 mm .0295 +0.80 mm .0315 +0.85 mm .0335 +0.90 mm .0354 +0.95 mm .0374 +1.00 mm .0394 +1.05 mm .0413 +1.10 mm .0433 +1.15 mm .0453 +1.20 mm .0472 +1.25 mm .0492 +1.30 mm .0512 +1.35 mm .0531 +1.40 mm .0551 +1.45 mm .0571 +1.50 mm .0591 +1.55 mm .0610 +1.60 mm .0630 +1.65 mm .0650 +1.70 mm .0669 +1.75 mm .0689 +1.80 mm .0709 +1.85 mm .0728 +1.90 mm .0748 +1.95 mm .0768 +2.00 mm .0787 +2.05 mm .0807 +2.10 mm .0827 +2.15 mm .0846 +2.20 mm .0866 +2.25 mm .0886 +2.30 mm .0906 +2.35 mm .0925 +2.40 mm .0945 +2.45 mm .0965 +2.50 mm .0984 +2.55 mm .1004 +2.60 mm .1024 +2.65 mm .1043 +2.70 mm .1063 +2.75 mm .1083 +2.80 mm .1102 +2.85 mm .1122 +2.90 mm .1142 +2.95 mm .1161 +3.00 mm .1181 +3.10 mm .1220 +3.15 mm .1240 +3.20 mm .1260 +3.25 mm .1280 +3.30 mm .1299 +3.40 mm .1339 +3.50 mm .1378 +3.60 mm .1417 +3.70 mm .1457 +3.75 mm .1476 +3.80 mm .1496 +3.90 mm .1535 +4.00 mm .1575 +4.10 mm .1614 +4.20 mm .1654 +4.25 mm .1673 +4.30 mm .1693 +4.40 mm .1732 +4.50 mm .1772 +4.60 mm .1811 +4.70 mm .1850 +4.75 mm .1870 +4.80 mm .1890 +4.90 mm .1929 +5.00 mm .1969 +5.10 mm .2008 +5.20 mm .2047 +5.25 mm .2067 +5.30 mm .2087 +5.40 mm .2126 +5.50 mm .2165 +5.60 mm .2205 +5.70 mm .2244 +5.75 mm .2264 +5.80 mm .2283 +5.90 mm .2323 +6.00 mm .2362 +6.10 mm .2402 +6.20 mm .2441 +6.25 mm .2461 +6.30 mm .2480 +6.40 mm .2520 +6.50 mm .2559 +6.60 mm .2598 +6.70 mm .2638 +6.75 mm .2657 +6.80 mm .2677 +6.90 mm .2717 +7.00 mm .2756 +7.10 mm .2795 +7.20 mm .2835 +7.25 mm .2854 +7.30 mm .2874 +7.40 mm .2914 +7.50 mm .2953 +7.60 mm .2992 +7.70 mm .3031 +8.00 mm .3150 +8.10 mm .3189 +8.20 mm .3228 +8.25 mm .3248 +8.30 mm .3268 +8.40 mm .3307 +8.50 mm .3346 +8.60 mm .3386 +8.70 mm .3425 +8.75 mm .3445 +8.80 mm .3465 +8.90 mm .3504 +9.00 mm .3543 +9.10 mm .3583 +9.20 mm .3622 +9.25 mm .3642 +9.30 mm .3661 +9.40 mm .3701 +9.50 mm .3740 +9.60 mm .3780 +9.70 mm .3819 +9.75 mm .3839 +9.80 mm .3858 +9.90 mm .3898 +10.00 mm .3937 +10.10 mm .3976 +10.20 mm .4016 +10.25 mm .4035 +10.30 mm .4055 +10.40 mm .4094 +10.50 mm .4134 +10.60 mm .4173 +10.70 mm .4213 +10.80 mm .4252 +10.90 mm .4291 +11.00 mm .4331 +11.10 mm .4370 +11.20 mm .4409 +11.25 mm .4429 +11.30 mm .4449 +11.40 mm .4488 +11.50 mm .4528 +11.60 mm .4567 +11.70 mm .4606 +11.75 mm .4626 +11.80 mm .4646 +11.90 mm .4685 +12.00 mm .4724 +12.50 mm .4921 +13.00 mm .5118 +13.50 mm .5315 +14.00 mm .5512 +14.50 mm .5709 +15.00 mm .5906 +15.50 mm .6102 +16.00 mm .6299 +16.50 mm .6496 +17.00 mm .6693 +17.50 mm .6890 +18.00 mm .7087 +18.50 mm .7283 +19.00 mm .7480 +19.50 mm .7677 +20.00 mm .7874 +20.50 mm .8071 +21.00 mm .8268 +21.50 mm .8465 +22.00 mm .8661 +22.50 mm .8858 +23.00 mm .9055 +23.50 mm .9252 +24.00 mm .9449 +24.50 mm .9646 +25.00 mm .9843 + Index: tags/1.2.7/doc-orig/new_gen/tab2html.sh =================================================================== --- tags/1.2.7/doc-orig/new_gen/tab2html.sh (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/tab2html.sh (revision 13657) @@ -0,0 +1,47 @@ +#!/bin/sh + +# Configuration: $1 is the number of col pairs in a row + +echo "" +echo "" +echo "" +awk -F "[\t]*" -v "cols=$1" ' +BEGIN { + len = 0 +} + +/^[@]/ { +# print header + print "" + sub("^@", "", $0) + for(n = 0; n < cols; n++) + print "" + for(c = 0; c < cols; c++) { + idx = c*rows + r + cell = CELL[idx] + if (cell == "") + cell = "
            " $1 "" $2 + + next +} + +# load data +(NF == 2) { + CELL[len] = "" $1 "" $2 + len++ +} + +END { + rows = len / cols + if (rows != int(rows)) + rows++; + rows = int(rows); + for(r = 0; r < rows; r++) { + print "
              " + print cell + } + } +} + +' +echo "
            " Property changes on: tags/1.2.7/doc-orig/new_gen/tab2html.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/doc-orig/new_gen/wire_size.tab =================================================================== --- tags/1.2.7/doc-orig/new_gen/wire_size.tab (nonexistent) +++ tags/1.2.7/doc-orig/new_gen/wire_size.tab (revision 13657) @@ -0,0 +1,100 @@ +@Drill
            Size Diameter
            (inches) +97 .0059 +96 .0063 +95 .0067 +94 .0071 +93 .0075 +92 .0079 +91 .0083 +90 .0087 +89 .0091 +88 .0095 +87 .0100 +86 .0105 +85 .0110 +84 .0115 +83 .0120 +82 .0125 +81 .0130 +80 .0135 +79 .0145 +78 .0160 +77 .0180 +76 .0200 +75 .0210 +74 .0225 +73 .0240 +72 .0250 +71 .0260 +70 .0280 +69 .0292 +68 .0310 +67 .0320 +66 .0330 +65 .0350 +64 .0360 +63 .0370 +62 .0380 +61 .0390 +60 .0400 +59 .0410 +58 .0420 +57 .0430 +56 .0465 +55 .0520 +54 .0550 +53 .0595 +52 .0635 +51 .0670 +50 .0700 +49 .0730 +48 .0760 +47 .0785 +46 .0810 +45 .0820 +44 .0860 +43 .0890 +42 .0935 +41 .0960 +40 .0980 +39 .0995 +38 .1015 +37 .1040 +36 .1065 +35 .1100 +34 .1110 +33 .1130 +32 .1160 +31 .1200 +30 .1285 +29 .1360 +28 .1405 +27 .1440 +26 .1470 +25 .1495 +24 .1520 +23 .1540 +22 .1570 +21 .1590 +20 .1610 +19 .1660 +18 .1695 +17 .1730 +16 .1770 +15 .1800 +14 .1820 +13 .1850 +12 .1890 +11 .1910 +10 .1935 +9 .1960 +8 .1990 +7 .2010 +6 .2040 +5 .2055 +4 .2090 +3 .2130 +2 .2210 +1 .2280 + + Index: tags/1.2.7/doc-orig/options.texi =================================================================== --- tags/1.2.7/doc-orig/options.texi (nonexistent) +++ tags/1.2.7/doc-orig/options.texi (revision 13657) @@ -0,0 +1,896 @@ +@c key options +@menu +* General Options:: +* General GUI Options:: +* GTK+ GUI Options:: +* lesstif GUI Options:: +* Colors:: +* Layer Names:: +* Paths:: +* Sizes:: +* Commands:: +* DRC Options:: +* BOM Creation:: +* Gerber Export:: +* Postscript Export:: +* Encapsulated Postscript Export:: +* PNG Options:: +* lpr Printing Options:: +* nelma Options:: +@end menu +@c options General Options +@node General Options +@section General Options +@c ./../src/main.c 434 +@ftable @code +@item --help +Show help on command line options. +@end ftable +@c ./../src/main.c 439 +@ftable @code +@item --version +Show version. +@end ftable +@c ./../src/main.c 443 +@ftable @code +@item --verbose +Be verbose on stdout. +@end ftable +@c ./../src/main.c 448 +@ftable @code +@item --copyright +Show copyright. +@end ftable +@c ./../src/main.c 453 +@ftable @code +@item --show-defaults +Show option defaults. +@end ftable +@c ./../src/main.c 458 +@ftable @code +@item --show-actions +Show available actions and exit. +@end ftable +@c ./../src/main.c 463 +@ftable @code +@item --dump-actions +Dump actions (for documentation). +@end ftable +@c ./../src/main.c 468 +@ftable @code +@item --grid-units-mm +Set default grid units. Can be mm or mil. Defaults to mil. +@end ftable +@c ./../src/main.c 686 +@ftable @code +@item --backup-interval +Time between automatic backups in seconds. Set to @code{0} to disable. +The default value is @code{60}. +@end ftable +@c ./../src/main.c 723 +@ftable @code +@item --groups +Layer group string. Defaults to @code{"1,c:2:3:4:5:6,s:7:8"}. +@end ftable +@c ./../src/main.c 788 +@ftable @code +@item --route-styles +A string that defines the route styles. Defaults to @* +@code{"Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000 + :Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600"} +@end ftable +@c ./../src/main.c 807 +@ftable @code +@item --element-path +A colon separated list of directories or commands (starts with '|'). +The path is passed to the program specified in @option{--element-command}. +@end ftable +@c ./../src/main.c 817 +@ftable @code +@item --action-script +If set, this file is executed at startup. +@end ftable +@c ./../src/main.c 822 +@ftable @code +@item --action-string +If set, this string of actions is executed at startup. +@end ftable +@c ./../src/main.c 827 +@ftable @code +@item --fab-author +Name of author to be put in the Gerber files. +@end ftable +@c ./../src/main.c 832 +@ftable @code +@item --layer-stack +Initial layer stackup, for setting up an export. A comma separated list of layer +names, layer numbers and layer groups. +@end ftable +@c ./../src/main.c 883 +@ftable @code +@item --save-last-command +If set, the last user command is saved. +@end ftable +@c ./../src/main.c 887 +@ftable @code +@item --save-in-tmp +If set, all data which would otherwise be lost are saved in a temporary file +@file{/tmp/PCB.%i.save} . Sequence @samp{%i} is replaced by the process ID. +@end ftable +@c ./../src/main.c 901 +@ftable @code +@item --reset-after-element +If set, all found connections are reset before a new component is scanned. +@end ftable +@c ./../src/main.c 906 +@ftable @code +@item --ring-bell-finished +Execute the bell command when all rats are routed. +@end ftable +@c options General GUI Options +@node General GUI Options +@section General GUI Options +@c ./../src/main.c 842 +@ftable @code +@item --pinout-offset-x +Horizontal offset of the pin number display. Defaults to @code{100mil}. +@end ftable +@c ./../src/main.c 847 +@ftable @code +@item --pinout-offset-y +Vertical offset of the pin number display. Defaults to @code{100mil}. +@end ftable +@c ./../src/main.c 852 +@ftable @code +@item --pinout-text-offset-x +Horizontal offset of the pin name display. Defaults to @code{800mil}. +@end ftable +@c ./../src/main.c 857 +@ftable @code +@item --pinout-text-offset-y +Vertical offset of the pin name display. Defaults to @code{-100mil}. +@end ftable +@c ./../src/main.c 862 +@ftable @code +@item --draw-grid +If set, draw the grid at start-up. +@end ftable +@c ./../src/main.c 866 +@ftable @code +@item --clear-line +If set, new lines clear polygons. +@end ftable +@c ./../src/main.c 870 +@ftable @code +@item --full-poly +If set, new polygons are full ones. +@end ftable +@c ./../src/main.c 874 +@ftable @code +@item --unique-names +If set, you will not be permitted to change the name of an component to match that +of another component. +@end ftable +@c ./../src/main.c 878 +@ftable @code +@item --snap-pin +If set, pin centers and pad end points are treated as additional grid points +that the cursor can snap to. +@end ftable +@c ./../src/main.c 892 +@ftable @code +@item --all-direction-lines +Allow all directions, when drawing new lines. +@end ftable +@c ./../src/main.c 897 +@ftable @code +@item --show-number +Pinout shows number. +@end ftable +@c options GTK+ GUI Options +@node GTK+ GUI Options +@section GTK+ GUI Options +@c ./../src/hid/gtk/gui-top-window.c 1615 +@ftable @code +@item --listen +Listen for actions on stdin. +@end ftable +@c ./../src/hid/gtk/gui-top-window.c 1621 +@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 +@c ./../src/hid/gtk/gui-top-window.c 1627 +@ftable @code +@item --pcb-menu +Location of the @file{gpcb-menu.res} file which defines the menu for the GTK+ GUI. +@end ftable +@c options lesstif GUI Options +@node lesstif GUI Options +@section lesstif GUI Options +@c ./../src/hid/lesstif/main.c 201 +@ftable @code +@item --listen +Listen for actions on stdin. +@end ftable +@c ./../src/hid/lesstif/main.c 207 +@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 +@c ./../src/hid/lesstif/main.c 213 +@ftable @code +@item --pcb-menu +Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI. +@end ftable +@c options Colors +@node Colors +@section Colors +@c ./../src/main.c 473 +@ftable @code +@item --black-color +Color value for black. Default: @samp{#000000} +@end ftable +@c ./../src/main.c 477 +@ftable @code +@item --black-color +Color value for white. Default: @samp{#ffffff} +@end ftable +@c ./../src/main.c 481 +@ftable @code +@item --background-color +Background color of the canvas. Default: @samp{#e5e5e5} +@end ftable +@c ./../src/main.c 486 +@ftable @code +@item --crosshair-color +Color of the crosshair. Default: @samp{#ff0000} +@end ftable +@c ./../src/main.c 491 +@ftable @code +@item --cross-color +Color of the cross. Default: @samp{#cdcd00} +@end ftable +@c ./../src/main.c 495 +@ftable @code +@item --via-color +Color of vias. Default: @samp{#7f7f7f} +@end ftable +@c ./../src/main.c 499 +@ftable @code +@item --via-selected-color +Color of selected vias. Default: @samp{#00ffff} +@end ftable +@c ./../src/main.c 504 +@ftable @code +@item --pin-color +Color of pins. Default: @samp{#4d4d4d} +@end ftable +@c ./../src/main.c 508 +@ftable @code +@item --pin-selected-color +Color of selected pins. Default: @samp{#00ffff} +@end ftable +@c ./../src/main.c 513 +@ftable @code +@item --pin-name-color +Color of pin names and pin numbers. Default: @samp{#ff0000} +@end ftable +@c ./../src/main.c 518 +@ftable @code +@item --element-color +Color of components. Default: @samp{#000000} +@end ftable +@c ./../src/main.c 522 +@ftable @code +@item --rat-color +Color of ratlines. Default: @samp{#b8860b} +@end ftable +@c ./../src/main.c 526 +@ftable @code +@item --invisible-objects-color +Color of invisible objects. Default: @samp{#cccccc} +@end ftable +@c ./../src/main.c 531 +@ftable @code +@item --invisible-mark-color +Color of invisible marks. Default: @samp{#cccccc} +@end ftable +@c ./../src/main.c 536 +@ftable @code +@item --element-selected-color +Color of selected components. Default: @samp{#00ffff} +@end ftable +@c ./../src/main.c 541 +@ftable @code +@item --rat-selected-color +Color of selected rats. Default: @samp{#00ffff} +@end ftable +@c ./../src/main.c 546 +@ftable @code +@item --connected-color +Color to indicate connections. Default: @samp{#00ff00} +@end ftable +@c ./../src/main.c 551 +@ftable @code +@item --off-limit-color +Color of off-canvas area. Default: @samp{#cccccc} +@end ftable +@c ./../src/main.c 556 +@ftable @code +@item --grid-color +Color of the grid. Default: @samp{#ff0000} +@end ftable +@c ./../src/main.c 560 +@ftable @code +@item --layer-color- +Color of layer @code{}, where @code{} is an integer from 1 to 16. +@end ftable +@c ./../src/main.c 578 +@ftable @code +@item --layer-selected-color- +Color of layer @code{}, when selected. @code{} is an integer from 1 to 16. +@end ftable +@c ./../src/main.c 597 +@ftable @code +@item --warn-color +Color of offending objects during DRC. Default value is @code{"#ff8000"} +@end ftable +@c ./../src/main.c 601 +@ftable @code +@item --mask-color +Color of the mask layer. Default value is @code{"#ff0000"} +@end ftable +@c options Layer Names +@node Layer Names +@section Layer Names +@c ./../src/main.c 691 +@ftable @code +@item --layer-name-1 +Name of the 1st Layer. Default is @code{"top"}. +@end ftable +@c ./../src/main.c 695 +@ftable @code +@item --layer-name-2 +Name of the 2nd Layer. Default is @code{"ground"}. +@end ftable +@c ./../src/main.c 699 +@ftable @code +@item --layer-name-3 +Name of the 3nd Layer. Default is @code{"signal2"}. +@end ftable +@c ./../src/main.c 703 +@ftable @code +@item --layer-name-4 +Name of the 4rd Layer. Default is @code{"signal3"}. +@end ftable +@c ./../src/main.c 707 +@ftable @code +@item --layer-name-5 +Name of the 5rd Layer. Default is @code{"power"}. +@end ftable +@c ./../src/main.c 711 +@ftable @code +@item --layer-name-6 +Name of the 6rd Layer. Default is @code{"bottom"}. +@end ftable +@c ./../src/main.c 715 +@ftable @code +@item --layer-name-7 +Name of the 7rd Layer. Default is @code{"outline"}. +@end ftable +@c ./../src/main.c 719 +@ftable @code +@item --layer-name-8 +Name of the 8rd Layer. Default is @code{"spare"}. +@end ftable +@c options Paths +@node Paths +@section Paths +@c ./../src/main.c 769 +@ftable @code +@item --lib-newlib +Top level directory for the newlib style library. +@end ftable +@c ./../src/main.c 778 +@ftable @code +@item --lib-name +The default filename for the library. +@end ftable +@c ./../src/main.c 783 +@ftable @code +@item --default-font +The name of the default font. +@end ftable +@c ./../src/main.c 794 +@ftable @code +@item --file-path +A colon separated list of directories or commands (starts with '|'). The path +is passed to the program specified in @option{--file-command} together with the selected +filename. +@end ftable +@c ./../src/main.c 802 +@ftable @code +@item --font-path +A colon separated list of directories to search the default font. Defaults to +the default library path. +@end ftable +@c ./../src/main.c 812 +@ftable @code +@item --lib-path +A colon separated list of directories that will be passed to the commands specified +by @option{--element-command} and @option{--element-contents-command}. +@end ftable +@c options Sizes +@node Sizes +@section Sizes +@c ./../src/main.c 606 +All parameters should be given with an unit. If no unit is given, 1/100 mil +(cmil) will be used. Write units without space to the +number like @code{3mm}, not @code{3 mm}. +Valid Units are: + @table @samp + @item km + Kilometer + @item m + Meter + @item cm + Centimeter + @item mm + Millimeter + @item um + Micrometer + @item nm + Nanometer + @item in + Inch (1in = 0.0254m) + @item mil + Mil (1000mil = 1in) + @item cmil + Centimil (1/100 mil) +@end table + +@ftable @code +@item --via-thickness +Default diameter of vias. Default value is @code{60mil}. +@end ftable +@c ./../src/main.c 611 +@ftable @code +@item --via-drilling-hole +Default diameter of holes. Default value is @code{28mil}. +@end ftable +@c ./../src/main.c 616 +@ftable @code +@item --line-thickness +Default thickness of new lines. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 621 +@ftable @code +@item --rat-thickness +Thickness of rats. Values from 1 to 19 are fixed width in screen pixels. +Anything larger means PCB units (i.e. 100 means "1 mil"). Default value +is @code{10mil}. +@end ftable +@c ./../src/main.c 625 +@ftable @code +@item --keepaway +Default minimum distance between a track and adjacent copper. +Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 629 +@ftable @code +@item --default-PCB-width +Default width of the canvas. Default value is @code{6000mil}. +@end ftable +@c ./../src/main.c 634 +@ftable @code +@item --default-PCB-height +Default height of the canvas. Default value is @code{5000mil}. +@end ftable +@c ./../src/main.c 639 +@ftable @code +@item --text-scale +Default text scale. This value is in percent. Default value is @code{100}. +@end ftable +@c ./../src/main.c 643 +@ftable @code +@item --alignment-distance +Specifies the distance between the board outline and alignment targets. +Default value is @code{2mil}. +@end ftable +@c ./../src/main.c 677 +@ftable @code +@item --grid +Initial grid size. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 681 +@ftable @code +@item --minimum polygon area +Minimum polygon area. +@end ftable +@c options Commands +@node Commands +@section Commands +@c ./../src/main.c 728 +pcb uses external commands for input output operations. These commands can be +configured at start-up to meet local requirements. The command string may include +special sequences @code{%f}, @code{%p} or @code{%a}. These are replaced when the +command is called. The sequence @code{%f} is replaced by the file name, +@code{%p} gets the path and @code{%a} indicates a package name. +@c ./../src/main.c 731 +@ftable @code +@item --font-command +Command to load a font. +@end ftable +@c ./../src/main.c 735 +@ftable @code +@item --file-command +Command to read a file. +@end ftable +@c ./../src/main.c 739 +@ftable @code +@item --element-command +Command to read a footprint. @* +Defaults to @code{"M4PATH='%p';export M4PATH;echo 'include(%f)' | m4"} +@end ftable +@c ./../src/main.c 745 +@ftable @code +@item --print-file +Command to print to a file. +@end ftable +@c ./../src/main.c 749 +@ftable @code +@item --lib-command-dir +Path to the command that queries the library. +@end ftable +@c ./../src/main.c 754 +@ftable @code +@item --lib-command +Command to query the library. @* +Defaults to @code{"QueryLibrary.sh '%p' '%f' %a"} +@end ftable +@c ./../src/main.c 759 +@ftable @code +@item --lib-contents-command +Command to query the contents of the library. @* +Defaults to @code{"ListLibraryContents.sh %p %f"} or, +on Windows builds, an empty string (to disable this feature). +@end ftable +@c ./../src/main.c 774 +@ftable @code +@item --save-command +Command to save to a file. +@end ftable +@c ./../src/main.c 798 +@ftable @code +@item --rat-command +Command for reading a netlist. Sequence @code{%f} is replaced by the netlist filename. +@end ftable +@c options DRC Options +@node DRC Options +@section DRC Options +@c ./../src/main.c 648 +All parameters should be given with an unit. If no unit is given, 1/100 mil +(cmil) will be used for backward compability. Valid units are given in section +@ref{Sizes}. +@c ./../src/main.c 652 +@ftable @code +@item --bloat +Minimum spacing. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 656 +@ftable @code +@item --shrink +Minimum touching overlap. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 660 +@ftable @code +@item --min-width +Minimum width of copper. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 664 +@ftable @code +@item --min-silk +Minimum width of lines in silk. Default value is @code{10mil}. +@end ftable +@c ./../src/main.c 668 +@ftable @code +@item --min-drill +Minimum diameter of holes. Default value is @code{15mil}. +@end ftable +@c ./../src/main.c 672 +@ftable @code +@item --min-ring +Minimum width of annular ring. Default value is @code{10mil}. +@end ftable +@c options BOM Creation +@node BOM Creation +@section BOM Creation +@c ./../src/hid/bom/bom.c 30 +@ftable @code +@item --bomfile +Name of the BOM output file. +@end ftable +@c ./../src/hid/bom/bom.c 35 +@ftable @code +@item --xyfile +Name of the XY output file. +@end ftable +@c ./../src/hid/bom/bom.c 41 +@ftable @code +@item --xy-unit +Unit of XY dimensions. Defaults to mil. +@end ftable +@c options Gerber Export +@node Gerber Export +@section Gerber Export +@c ./../src/hid/gerber/gerber.c 338 +@ftable @code +@item --gerberfile +Gerber output file prefix. Can include a path. +@end ftable +@c ./../src/hid/gerber/gerber.c 344 +@ftable @code +@item --all-layers +Output contains all layers, even empty ones. +@end ftable +@c ./../src/hid/gerber/gerber.c 350 +@ftable @code +@item --verbose +Print file names and aperture counts on stdout. +@end ftable +@c options Postscript Export +@node Postscript Export +@section Postscript Export +@c ./../src/hid/ps/ps.c 149 +@ftable @code +@item --psfile +Name of the postscript output file. Can contain a path. +@end ftable +@c ./../src/hid/ps/ps.c 155 +@ftable @code +@cindex drill-helper +@item --drill-helper +Print a centering target in large drill holes. +@end ftable +@c ./../src/hid/ps/ps.c 161 +@ftable @code +@cindex align-marks +@item --align-marks +Print alignment marks on each sheet. This is meant to ease alignment during exposure. +@end ftable +@c ./../src/hid/ps/ps.c 167 +@ftable @code +@item --outline +Print the contents of the outline layer on each sheet. +@end ftable +@c ./../src/hid/ps/ps.c 172 +@ftable @code +@item --mirror +Print mirror image. +@end ftable +@c ./../src/hid/ps/ps.c 178 +@ftable @code +@item --fill-page +Scale output to make the board fit the page. +@end ftable +@c ./../src/hid/ps/ps.c 184 +@ftable @code +@item --auto-mirror +Print mirror image of appropriate layers. +@end ftable +@c ./../src/hid/ps/ps.c 190 +@ftable @code +@item --ps-color +Postscript output in color. +@end ftable +@c ./../src/hid/ps/ps.c 196 +@ftable @code +@cindex ps-bloat +@item --ps-bloat +Amount to add to trace/pad/pin edges. +@end ftable +@c ./../src/hid/ps/ps.c 202 +@ftable @code +@cindex ps-invert +@item --ps-invert +Draw objects as white-on-black. +@end ftable +@c ./../src/hid/ps/ps.c 208 +@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 +@c ./../src/hid/ps/ps.c 214 +@ftable @code +@cindex psfade +@item --psfade +Fade amount for assembly drawings (0.0=missing, 1.0=solid). +@end ftable +@c ./../src/hid/ps/ps.c 220 +@ftable @code +@item --scale +Scale value to compensate for printer sizing errors (1.0 = full scale). +@end ftable +@c ./../src/hid/ps/ps.c 226 +@ftable @code +@cindex multi-file +@item --multi-file +Produce multiple files, one per page, instead of a single multi page file. +@end ftable +@c ./../src/hid/ps/ps.c 232 +@ftable @code +@item --xcalib +Paper width. Used for x-Axis calibration. +@end ftable +@c ./../src/hid/ps/ps.c 238 +@ftable @code +@item --ycalib +Paper height. Used for y-Axis calibration. +@end ftable +@c ./../src/hid/ps/ps.c 244 +@ftable @code +@item --drill-copper +Draw drill holes in pins / vias, instead of leaving solid copper. +@end ftable +@c ./../src/hid/ps/ps.c 250 +@ftable @code +@cindex show-legend +@item --show-legend +Print file name and scale on printout. +@end ftable +@c options Encapsulated Postscript Export +@node Encapsulated Postscript Export +@section Encapsulated Postscript Export +@c ./../src/hid/ps/eps.c 78 +@ftable @code +@item --eps-file +Name of the encapsulated postscript output file. Can contain a path. +@end ftable +@c ./../src/hid/ps/eps.c 84 +@ftable @code +@item --eps-scale +Scale EPS output by the parameter @samp{num}. +@end ftable +@c ./../src/hid/ps/eps.c 90 +@ftable @code +@cindex as-shown (EPS) +@item --as-shown +Export layers as shown on screen. +@end ftable +@c ./../src/hid/ps/eps.c 96 +@ftable @code +@item --monochrome +Convert output to monochrome. +@end ftable +@c ./../src/hid/ps/eps.c 102 +@ftable @code +@cindex only-visible +@item --only-visible +Limit the bounds of the EPS file to the visible items. +@end ftable +@c options PNG Options +@node PNG Options +@section PNG Options +@c ./../src/hid/png/png.c 168 +@ftable @code +@item --outfile +Name of the file to be exported to. Can contain a path. +@end ftable +@c ./../src/hid/png/png.c 174 +@ftable @code +@item --dpi +Scale factor in pixels/inch. Set to 0 to scale to size specified in the layout. +@end ftable +@c ./../src/hid/png/png.c 180 +@ftable @code +@item --x-max +Width of the png image in pixels. No constraint, when set to 0. +@end ftable +@c ./../src/hid/png/png.c 186 +@ftable @code +@item --y-max +Height of the png output in pixels. No constraint, when set to 0. +@end ftable +@c ./../src/hid/png/png.c 192 +@ftable @code +@item --xy-max +Maximum width and height of the PNG output in pixels. No constraint, when set to 0. +@end ftable +@c ./../src/hid/png/png.c 198 +@ftable @code +@item --as-shown +Export layers as shown on screen. +@end ftable +@c ./../src/hid/png/png.c 204 +@ftable @code +@item --monochrome +Convert output to monochrome. +@end ftable +@c ./../src/hid/png/png.c 210 +@ftable @code +@item --only-vivible +Limit the bounds of the exported PNG image to the visible items. +@end ftable +@c ./../src/hid/png/png.c 216 +@ftable @code +@item --use-alpha +Make the background and any holes transparent. +@end ftable +@c ./../src/hid/png/png.c 222 +@ftable @code +@item --format +File format to be exported. Parameter @code{} can be @samp{PNG}, +@samp{GIF}, or @samp{JPEG}. +@end ftable +@c ./../src/hid/png/png.c 228 +@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. +@end ftable +@c ./../src/hid/png/png.c 234 +@ftable @code +@cindex photo-mode +@item --photo-mode +Export a photo realistic image of the layout. +@end ftable +@c ./../src/hid/png/png.c 240 +@ftable @code +@item --photo-flip-x +In photo-realistic mode, export the reverse side of the layout. Left-right flip. +@end ftable +@c ./../src/hid/png/png.c 246 +@ftable @code +@item --photo-flip-y +In photo-realistic mode, export the reverse side of the layout. Up-down flip. +@end ftable +@c options lpr Printing Options +@node lpr Printing Options +@section lpr Printing Options +@c ./../src/hid/lpr/lpr.c 33 +@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. +@c options nelma Options +@node nelma Options +@section nelma Options +@c ./../src/hid/nelma/nelma.c 157 +@ftable @code +@item -- basename +File name prefix. +@end ftable +@c ./../src/hid/nelma/nelma.c 163 +@ftable @code +@item --dpi +Horizontal scale factor (grid points/inch). +@end ftable +@c ./../src/hid/nelma/nelma.c 169 +@ftable @code +@item --copper-height +Copper layer height (um). +@end ftable +@c ./../src/hid/nelma/nelma.c 175 +@ftable @code +@item --substrate-height +Substrate layer height (um). +@end ftable +@c ./../src/hid/nelma/nelma.c 181 +@ftable @code +@item --substrate-epsilon +Substrate relative epsilon. +@end ftable Index: tags/1.2.7/doc-orig/pad.pcb =================================================================== --- tags/1.2.7/doc-orig/pad.pcb (nonexistent) +++ tags/1.2.7/doc-orig/pad.pcb (revision 13657) @@ -0,0 +1,911 @@ +# release: pcb-bin 1.99q + +PCB["pad" 600000 500000] + +Grid[2000.00000000 0 0 1] +Cursor[88600 72400 2.000000] +Thermal[0.500000] +DRC[699 400 800 800 1000 750] +Flags(0x0000000000000840) +Groups("1,s:2,c:3:4:5:6:7:8") +Styles["Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,200,2402,1181,600"] + +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[500 5000 1500 5000 800] + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[0 2000 1000 1000 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[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2500 3000 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 3000 2000 3500 800] + SymbolLine[0 3000 1500 3000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[0 5000 2500 2500 800] + SymbolLine[2500 1000 2500 2500 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + 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[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2500 800] + SymbolLine[1500 3000 2000 2500 800] +) +Symbol['9' 1200] +( + SymbolLine[0 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 1500 0 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 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 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[500 3000 2000 3000 800] + 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] +) +Symbol['C' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 3000 1500 3000 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 3000 1500 3000 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[0 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] +) +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 2500 800] + SymbolLine[1500 2500 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 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 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 4000 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[500 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 1000 2000 4000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 1500 3500 800] + SymbolLine[1500 3500 3000 5000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 800] + SymbolLine[2500 4000 2500 5000 800] + SymbolLine[0 4000 0 5000 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[2500 1000 2500 1500 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 1000 2500 800] + SymbolLine[1000 2500 2000 1500 800] + SymbolLine[2000 1000 2000 1500 800] + SymbolLine[1000 2500 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[2500 1000 2500 1500 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[0 4000 0 5000 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 2500 800] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2500 800] + 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 3000 2000 4000 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] +) +Layer(1 "component") +( + Line[106000 144000 262000 144000 1000 2000 "clearline"] + Line[106000 144000 106000 84000 1000 2000 "clearline"] + Line[106000 84000 262000 84000 1000 2000 "clearline"] + Line[262000 84000 262000 144000 1000 2000 "clearline"] +) +Layer(2 "solder") +( + Line[256000 90000 256000 138000 1000 2000 "clearline"] + Line[112000 138000 112000 90000 1000 2000 "clearline"] + Line[112000 90000 256000 90000 1000 2000 "clearline"] + Line[112000 138000 256000 138000 1000 2000 "clearline"] +) +Layer(3 "GND") +( +) +Layer(4 "power") +( +) +Layer(5 "signal1") +( + Polygon("clearpoly") + ( + [118000 96000] [250000 96000] [250000 132000] [118000 132000] + ) +) +Layer(6 "signal2") +( +) +Layer(7 "unused") +( +) +Layer(8 "unused") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[118000 96000 118000 132000 500 2000 "clearline"] + Line[118000 132000 154000 132000 500 2000 "clearline"] + Line[154000 132000 154000 96000 500 2000 "clearline"] + Line[154000 96000 118000 96000 500 2000 "clearline"] + Line[136000 152000 136000 120000 500 1200 "clearline"] + Line[136000 120000 132000 124000 500 1200 "clearline"] + Line[132000 114000 140000 114000 1010 1200 "clearline"] + Line[140000 124000 136000 120000 500 1200 "clearline"] + Line[98000 90000 94000 94000 500 1200 "clearline"] + Line[214000 76000 250000 76000 500 1200 "clearline"] + Line[98000 138000 98000 90000 500 1200 "clearline"] + Line[270000 96000 266000 100000 500 1200 "clearline"] + Line[136000 110000 136000 118000 1010 1200 "clearline"] + Line[214000 96000 214000 132000 500 2000 "clearline"] + Line[252000 132000 276000 132000 500 1200 "clearline"] + Line[218000 72000 214000 76000 500 1200 "clearline"] + Line[214000 76000 218000 80000 500 1200 "clearline"] + Line[270000 96000 274000 100000 500 1200 "clearline"] + Line[252000 96000 276000 96000 500 1200 "clearline"] + Line[214000 132000 250000 132000 500 2000 "clearline"] + Line[136000 90000 140000 86000 500 1200 "clearline"] + Line[232000 150000 232000 120000 500 1200 "clearline"] + Line[236000 124000 232000 120000 500 1200 "clearline"] + Line[232000 110000 232000 118000 1010 1200 "clearline"] + Line[232000 120000 228000 124000 500 1200 "clearline"] + Line[204000 114000 212000 114000 500 1200 "clearline"] + Line[212000 114000 208000 110000 500 1200 "clearline"] + Line[212000 114000 208000 118000 500 1200 "clearline"] + Line[214000 94000 214000 70000 500 1200 "clearline"] + Line[250000 94000 250000 70000 500 1200 "clearline"] + Line[204000 114000 204000 48000 500 1200 "clearline"] + Line[136000 90000 132000 86000 500 1200 "clearline"] + Line[270000 132000 266000 128000 500 1200 "clearline"] + Line[250000 132000 250000 96000 500 2000 "clearline"] + Line[250000 96000 214000 96000 500 2000 "clearline"] + Line[160000 90000 112000 90000 500 2000 "clearline"] + Line[160000 138000 112000 138000 500 2000 "clearline"] + Line[112000 90000 112000 138000 500 2000 "clearline"] + Line[160000 90000 160000 138000 500 2000 "clearline"] + Line[136000 74000 136000 90000 500 1200 "clearline"] + Line[270000 132000 274000 128000 500 1200 "clearline"] + Line[228000 114000 236000 114000 1010 1200 "clearline"] + Line[270000 132000 270000 96000 500 1200 "clearline"] + Line[250000 76000 246000 72000 500 1200 "clearline"] + Line[250000 76000 246000 80000 500 1200 "clearline"] + Line[92000 90000 110000 90000 500 1200 "clearline"] + Line[186000 96000 190000 92000 500 1200 "clearline"] + Line[186000 96000 182000 92000 500 1200 "clearline"] + Line[186000 64000 186000 96000 500 1200 "clearline"] + Line[98000 138000 94000 134000 500 1200 "clearline"] + Line[98000 138000 102000 134000 500 1200 "clearline"] + Line[98000 90000 102000 94000 500 1200 "clearline"] + Line[92000 138000 110000 138000 500 1200 "clearline"] + Line[214000 138000 210000 142000 500 1200 "clearline"] + Line[218000 142000 214000 138000 500 1200 "clearline"] + Line[214000 168000 214000 138000 500 1200 "clearline"] + Line[192000 144000 188000 148000 500 1200 "clearline"] + Line[196000 148000 192000 144000 500 1200 "clearline"] + Line[192000 184000 192000 144000 500 1200 "clearline"] + Line[168000 144000 164000 148000 500 1200 "clearline"] + Line[172000 148000 168000 144000 500 1200 "clearline"] + Line[168000 176000 168000 144000 500 1200 "clearline"] + Line[168000 132000 172000 128000 500 1200 "clearline"] + Line[168000 132000 164000 128000 500 1200 "clearline"] + Line[168000 120000 168000 132000 500 1200 "clearline"] + Text[106000 152000 0 200 "(X0,Y0)" ""] + Text[224000 150000 0 200 "(X1,Y1)" ""] + Text[226000 72000 1 200 "SIZE" ""] + Text[41000 106000 0 200 "Mask Size" ""] + Text[56000 62000 0 200 "Mask Aperture" ""] + Text[130000 52000 0 200 "Pad Shape" ""] + Text[272000 110000 0 200 "SIZE" ""] + Text[132000 36000 0 200 "Pad Aperture" ""] + Text[210000 168000 0 200 "Soldermask Opening" ""] + Text[188000 186000 0 200 "Clearance to non-connecting" ""] + Text[188000 198000 0 200 "polygons" ""] + Text[102000 176000 0 200 "Clearance/2" ""] +) Index: tags/1.2.7/doc-orig/pad.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/pad.pdf =================================================================== --- tags/1.2.7/doc-orig/pad.pdf (nonexistent) +++ tags/1.2.7/doc-orig/pad.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/pad.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/pad.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/pad.png =================================================================== --- tags/1.2.7/doc-orig/pad.png (nonexistent) +++ tags/1.2.7/doc-orig/pad.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/pad.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/pcb.1 =================================================================== --- tags/1.2.7/doc-orig/pcb.1 (nonexistent) +++ tags/1.2.7/doc-orig/pcb.1 (revision 13657) @@ -0,0 +1,45 @@ +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +.\" + +.TH PCB 1 + +.SH NAME +.B pcb +\- Printed circuit board layout tool + +.SH SYNOPSIS +.B pcb [options] [pcb file] + +.SH DESCRIPTION +The +.B pcb +program is a tool for the layout of printed circuit boards. +The complete manual for +.B pcb +is provided in a GNU texinfo format as well as HTML and PDF. +The texinfo version of the manual is typically viewed with the +.B info +program or alternatively with +.B emacs +or a graphical info viewer such as +.B tkinfo. +The PDF and HTML documentation is typically installed as +/usr/local/share/pcb/pcb.html and /usr/local/share/pcb/pcb.pdf. +The prefix "/usr/local" may vary at your site. + + + + Index: tags/1.2.7/doc-orig/pcb.css =================================================================== --- tags/1.2.7/doc-orig/pcb.css (nonexistent) +++ tags/1.2.7/doc-orig/pcb.css (revision 13657) @@ -0,0 +1,11 @@ +table.cartouche { + border-collapse: collapse; + border: 1px solid #800000; + width: 100%; +} +table.cartouche td { + padding: 4px; +} +pre.format { + font-family: monospace; +} Index: tags/1.2.7/doc-orig/pcb.html =================================================================== --- tags/1.2.7/doc-orig/pcb.html (nonexistent) +++ tags/1.2.7/doc-orig/pcb.html (revision 13657) @@ -0,0 +1,12884 @@ + + +pcb-rnd documentation + + + + + + + +

            pcb-rnd documentation

            +
            + +


            +Next: , +Up: (dir) + +
            + +

            pcb-rnd

            + +

            This document is a temporary manual for the geda-related project +pcb-rnd, which is forked from pcb. + +

            pcb-rnd is a program used for designing printed circuit board +layouts. + + +

            + + +
            + +


            +Next: , +Previous: Top, +Up: Top + +
            + +

            Copying, License & Attribution

            +

            Copyright © 1994,1995,1996,1997 Thomas Nau + +

            Copyright © 1998,1999,2000,2001,2002 harry eaton + +

            © insert new copyright here:

            + +

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

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

            + +


            +Next: , +Previous: Copying, License, & Atribution, +Up: Top + +
            + +

            Background

            + +

            pcb-rnd is a tool for +laying out cicuit boards and creating export files required to fabricate them. + +

            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. + +

            Release history and credits for Pcb can be found in + the documentation files in mainline Pcb, and currently as of this writing at + http://pcb.geda-project.org/manual.html + + +

            + +


            +Next: , +Previous: Background, +Up: Top + +
            + +

            1 Overview

            + +

            +pcb-rnd is an open source printed circuit board editor. +pcb-rnd includes many professional features such as: +

              +
            • Up to 16 copper layer designs by default. By changing a compile time setting, this +can be set as high as needed. +
            • RS-274X (Gerber) output +
            • NC Drill output +
            • Centroid (X-Y) data output +
            • Postscript and Encapsulated Postscript output +
            • Autorouter +
            • Trace optimizer +
            • Rats nest +
            • Design Rule Checker (DRC) +
            • Connectivity verification +
            • pcb-rnd is Free Software +
            • Can interoperate with free schematic capture tools such as gEDA and + xcircuit +
            • Runs under Linux, NetBSD, Solaris, and other similar operating +systems. +
            • Windows version is available +
            + + +
            + +


            +Next: , +Previous: Overview, +Up: Top + +
            + +

            2 Introduction

            + +

            +Each layout consists of several, mostly independent, objects. This chapter +gives an overview of the object types and their relationship to each other. +For a complete description of how to use pcb-rnd, refer to +Getting Started. +The layout is generated on-screen on a grid that can have its origin +at any desired location. +The X coordinate increases to the right, Y increases down to the bottom. +All distances and sizes in pcb-rnd are measured in mils +(0.001 inch). One unit on the coordinate display is one mil in +distance on the board. +The grid may be set on a metric pitch, but is only correct to within +the nearest +/- 0.01 mil because pcb-rnd stores all dimensions as +integer multiples of 1/100 of a mil or 0.00001 inch. + +

            The sections in this chapter are sorted by the +order of appearance of the objects within a layout file. + +

            + +
            + +


            +Next: , +Up: Intro + +
            + +

            2.1 Symbols

            + +

            +The top object is the layout itself. It uses a set of symbols +that resides at the first logical level. Each symbol is uniquely identified +by a seven bit ASCII code. All layout objects share the same set of +symbols. These symbols are used to form text objects on the silkscreen +and copper layers. Undefined symbols are drawn as filled rectangles. + +

            Every font file is preprocessed by a user-defined command when it is loaded. +For details see ‘fontCommand’, Resources. + +

            + +


            +Next: , +Previous: Symbol Objects, +Up: Intro + +
            + +

            2.2 Vias

            + +

            +Vias provide through-hole connectivity across all layers. +While vias look a lot like element pins, don't use vias +for adding elements to the layout, even if that seems +easier than creating a new element. The default solder-mask +will cover over vias, so you won't be able to solder to them. +Of course, you can change this so that vias also have +solder-mask cut-outs, but it is not the default. +Vias are also useful for defining arbitrary drill points such as +those used for mounting a board. Vias used in this way have +a special flag set so that they have no annular copper ring, +and also appear in the unplated drill file. Ctrl-H key over +a via switches it between being a pure-mounting hole and a regular via. +You can assign a name to a via, which is useful during the creation +of new element definitions. +Each via exists on all copper layers. (i.e. +blind and buried vias are not supported) + +

            + +


            +Next: , +Previous: Via Objects, +Up: Intro + +
            + +

            2.3 Elements

            + +

            +Elements represent the components on a board. +Elements are loaded from ASCII coded files in a +similar manner to the layout file itself, or from the +library selector window. +An element is composed of lines and arcs on the silk-screen +layer (used to define the package outline), pins +(or pads for SMD) and three labels that define the +description, the element's layout-name (which also +appears on the silk-screen layer) and its value. You +can choose which of the names are displayed on the screen +with the Screen menu; however, the silk screen in +the printout will always show the layout-name. +Element pins are contained on the first logical level +and so reside on all layers, but the pads of surface-mount +elements reside on only the component or solder +layers. An element can have a mixture of pins, pads +(on one or both sides), and mounting holes. + +

            A mark is used to position the element with +respect to the cross hair during pasting. +The mark will lie on a grid point when the element +is positioned. The mark is drawn as a small diamond +shape, but is only visible when both the silk +and pins/pads layers are visible. +All parts of an element are treated as one unit, except for +the name. +It is not possible to delete a single pin or move +only part of an element on the layout. +You can resize separate pieces of an element, +but doing so is usually a bad idea. You can move/rotate +the element name independently of the element it belongs +to. When you move an element name, a line is draw from +the cursor to the element mark so it is easy to tell +which element the name belongs to. + +

            Each pin and pad has two string identifiers, one is the +"name" which is a functional description of the pin +(e.g. "clock in") and the other is the "number" of the +pin which is used to identify it in a netlist. The "number" +is usually an integer, but it can be any string. You +can edit the "name" of each pin of an element, but the +"number" is embedded in the element definition and is +determined when the new element is first created. +Pads are similar to lines on a layer but they must be oriented +either vertically or horizontally. +Pads can have either rounded or square ends. Pins +can be round, square, or octagonal. + +

            Elements are supported by several special layers: silk, pins/pads and +far-side. The silk layer shows the package outline and +also holds legend text and element names. The pins/pads layer is used to toggle +whether the element's pins and pads are displayed. The far-side layer controls visibility +of objects (silkscreen and pads) that are on the far (i.e. not currently viewed) side +of the board. + +

            The “oldlib” style of footprint libraries distributed with +pcb-rnd rely upon the M4 macro processor. M4 is typically +installed under the name m4 on most unix-like operating +systems. It is recommended that you use the GNU version of M4 to +avoid limitations found in some vendor implementations. See the m4 +man page on your system for more information. +Every element file is preprocessed by a user-defined command when the file is read. +For details see ‘elementCommand’, Resources. m4, the default +value of ‘elementCommand’, allows you to create libraries for +package definitions that are shared by all elements. +The old element libraries distributed with pcb-rnd expect m4 or an +equivalent to be the elementCommand. The new library scheme simply has +each element stored in a self-contained file, so there is no need to learn +m4 to add to the libraries. + +

            pcb-rnd can create a list of +all connections from one (or all) elements to the others or a list of +unconnected pins. +It can also verify the layout connections against a netlist file. +The element's ‘layout-name’ is the name used to identify the element +in a netlist file (see Netlist File). + +

            The old libraries, or very old (pre-1.6) layout files may have +incorrect pin numbering since there was no concept of pin numbers +when they were created. pcb-rnd uses the order of appearance of +the pin definitions in the layout or library file if it uses the +old format, but there is no guarantee that it will be correct for +these old objects. + +

            Be aware that a few of the old library parts may still be incorrectly +implemented regarding pin-numbering. All of the DIL (Dual- +Inline-Pins) parts are correct and most of the others are too, +but you should verify the pin numbering +of any non-DIL part before using an old library part. +(use the ‘generate object report’ in the Info menu +to see what pcb-rnd thinks a pin's number is) +All of the old +library names begin with a ~, so you can easily identify them. +The old libraries also may contain other sorts of errors, +including incorrect pin spacing, silkscreen overlapping solder areas, etc. +Check carefully any element in the old library before using it! +As the new library grows, the old library will be pared down to +at least remove all of the elements with errors, but this will +take time. + +

            You can make your own element definitions graphically now. +Simply draw vias for the pins, lines on the solder and/or +component layers for surface-mount pads (they must be either horizontal +or vertical), +and lines and arcs on the silkscreen layer for the silkscreen +outline. You should name (N key) each via and copper line with the pin number. +Once you are happy with the geometry, select everything that is to become part of +the element, then choose ‘convert selection to element’ from the Select menu. +Afterwords you can make pin (or pad) one +square if you like, and give the element its various names. You can also give +the pins and pads their functional names. Note that the +element mark corresponds to the position you click after choosing the +conversion from the menu, so decide where the mark goes and make +sure it falls on a grid point before you request the conversion. +If the vias/lines are not named, then the pin numbering will correspond to the +order in which they were placed. + +

            When you create a new element, remember that silkscreen lines +should never overlap the copper part of the +pins or pads, as this can interfere with soldering. The silkscreen +should identify the maximum extent of the element package so it +is easy to see how close elements can be placed together. + +

            If you want to make an element similar to an existing one, you can +break an element into constituent pieces from the Buffer menu. +Paste the pieces to the layout, make the necessary changes, then +convert it back into an element. If the pin numbers haven't changed, +there is no need to name each via/line as they are pre-named when +the element was broken apart. When you create a new element, you +can save it to a file in order to have easy access to it the next +time you run pcb-rnd. + +

            + +


            +Next: , +Previous: Element Objects, +Up: Intro + +
            + +

            2.4 Layers

            + +

            +Every layout consists of several layers that can be used independently +or treated as a group. +Layer groups can be used to logically separate (and color-code) +different traces (e.g. power and signal); however, all +layers within a group reside on the same physical +copper layer of a board, so using different layers within the same +group won't provide electrical separation where they touch or overlap. +For details, see ‘layerGroups’, Resources. +Each layer is drawn in a color defined in the resource file +and identified by a name that you can change (for details +see ‘layerColor’, Resources.) +Layers are really just containers for line, arc, polygon, and text objects. The +component and solder layers contain SMD elements as well, but the +file structure doesn't reflect that fact directly. + +

            Each layer group +represents a physical layer on the printed circuit board. If you want to make +a four layer board, you'll need to have at least four layer groups. +Connections between layer groups are established only through element pins and vias. +The relationship between a specific layer and the board itself is configurable from +the ‘Edit layer groups’ option in the Settings menu. +The layer groups corresponding to the physical layers: component-side +and solder-side are always defined and you must map at least one +logical layer to each, even if you plan to make a single-sided board. +You are not obligated to put tracks on either of them. +Surface mount elements always reside on either the component-side or the +solder-side layer group. When you paste an element from the buffer, +it will go onto whichever side of the board you are viewing. +You can swap which side of the board you are viewing by pressing +the Tab key, or by selecting ‘view solder side’ from the +Screen menu. +The layer groups just have a name or number associated with them - where +they are sandwiched in the board is left for you to tell the +manufacturer. + +

            The silkscreen layer is special because there are actually two silkscreen +layers, one for the top (component) and one for the bottom (solder) side +of the board. Which silk layer you draw on is determined by the side of the +board that you are viewing. If you are viewing the component side, then +drawing on the silk layer draws to the component-side silk layer. + +

            The netlist layer is another special layer. It shows rat's-nest lines +(i.e. guides that show how the netlist expects the element to interconnect). +If you make this the active layer, you can use the Line tool to add +entries into the netlist, or to delete connections from the netlist +window. Except for these two purposes, you should not +make the netlist layer the active layer. Usually there is no need to +do this because a separate schematic package should be used to create the +netlist. pcb-rnd can automatically draw all of the rats from +the netlist. In some cases you may want to make a small change without +going to the trouble of modifying the schematic, which is why this +facility is provided. + +

            + +


            +Next: , +Previous: Layer Objects, +Up: Intro + +
            + +

            2.5 Lines

            + +

            +Lines are used to draw tracks on the pc board. +When in the line mode, each Btn1 +press establishes one end of a line. +Once the second point is defined, the line is drawn +and a new line started where the first one ended. +You can abandon the new starting point in favor +of another by pressing Ctrl-Btn1, or +Btn3, but don't use Btn2. +The undo function (U key or ‘undo last operation’ +from the Edit menu) will take you back +point by point if you use it while in the line mode. + +

            New lines can be restricted to 45 degree angles if desired. You can toggle this +restriction on and off while creating lines by pressing the period key. +If the 45 degree restriction is turned on, then the / (forward slash) key +can be used to cycle through three different modes of 45 degree line creation. +One mode just creates a single line forced to the nearest 45 degree vector. The next +mode creates two lines from the start to end points such that the first line leaves the +start point at a 90 degree vector, and the second line enters the end point on a 45 +degree vector. The last mode creates two lines such that the first line leaves the +start point on a 45 degree vector and arrives at the end point on a 90 degree vector. +You can temporarily swap between the last two modes by holding the Shift key down. + +

            It is simple to edit a line object by breaking it into pieces (insert point mode), +moving an end point or the whole line (Arrow tool), +or changing the layer it resides on (M key moves the line under the pointer +to the active layer). +In the case when two line segments meet at exactly the same +point you can delete the intermediate point, otherwise the delete tool removes an entire line. +Feel free to experiment +since pcb-rnd will allow you to undo and redo anything that materially affects your work. +If you switch active layers in the midst of placing lines a via will automatically be +placed, when necessary, in order to continue the connection. + +

            If you draw a line inside a polygon, it will either plow through the +polygon creating a clearance, or touch the polygon. This behavior is +selectable in the Settings menu for new lines. To change the +behavior of an existing line, hit the J key with the cross hair +over the line. You can increase the size of the clearance by 2 mils on +each edge with the with the +K key. Shift-K will decrease the clearance by 2 mils. +The increment may be changed from 2 mils through the application +resource file. +The clearance can be also increased, decreased and set +by the ChangeClearSize action. + +

            Lines do not need to intersect the center of a pin, pad, via, or other +line for pcb-rnd to understand that they make electrical connection. +If the connection is too tenuous, running the design rule checker will report +that the connection may break if the line width shrinks slightly. + +

            + +


            +Next: , +Previous: Line Objects, +Up: Intro + +
            + +

            2.6 Arcs

            + +

            +pcb-rnd can handle arcs of any angular extent, but when you +create an arc with the Arc tool, it will +be a quarter circle (this means they always bend a right angle). Arcs are very similar +to lines otherwise. They are created on the active layer and have the same thickness +that new lines will have. The various clicks for creating lines work pretty much the +same way for creating arcs. +In order to make the arc curve in the desired direction, drag the mouse along +the tangent line from the starting position towards the end position. If the grid is +too coarse, it may not be possible to distinguish whether you've moved over then up, +or up then over, so if you can't seem to make the arc go in the direction you want, try pressing +the Shift key while drawing the arc. Decreasing the grid spacing may also help. +Alternatively you can draw the wrong arc, then +rotate and move it where you want. Like the Line tool, after an arc is drawn a new +starting point is established at the end point. + +

            Whenever a starting point is established +by either the Line or Arc tools it will be retained if you switch directly between the +tools (e.g. F2 key for Lines, F8 key for Arcs. Arcs can either touch or +clear polygons just like lines do. Of course connection +searches, undo and all the other features you'd expect work with arcs too. + +

            + +


            +Next: , +Previous: Arc Objects, +Up: Intro + +
            + +

            2.7 Polygons

            + +

            +Sometimes it's useful to fill large areas with solid copper. +The way to do this is with polygons. +Polygons can be created in either the polygon mode or the rectangle mode. +In the polygon mode, you'll have to define each corner of the polygon +with a mouse click (Btn1). When the last point is clicked +exactly on top of the starting point, the polygon is finished. +Since this can be hard to do, the Shift-P key will enter the +final point for you, closing the polygon. +If the 45 degree angle restriction is turned on +and you try to close the polygon when it is not possible, you'll get a +warning instead. If you haven't finished entering a polygon, but want to +undo one (or more) of the points that you've already defined, use the +undo command (U key). + +

            With the rectangle tool, defining +the two diagonally opposite corners is sufficient, but of course the resulting +polygon is a rectangle. +Like lines, a polygon can by edited by deleting, inserting and moving the points +that define it. Pins and vias always clear through polygons without +touching them when first positioned. You must add a thermal with the thermal +tool in order to connect pins and vias to polygons. Thermals can be added and removed by +clicking Btn1 with the thermal tool over the pin or via. +The thermal tool always +places a thermal to polygons on the active layer, so if the tool doesn't +seem to work, it's probably because the polygon you want to touch is not +on the active layer. You can change the style of thermal used or make +a solid connection by holding down Shift while clicking +Btn1 with the thermal tool over the pin or via. + +

            pcb-rnd is capable of handling complex polygons, but +using a number of simpler ones improves performance of the connection tracing code. +You also must be careful not to create polygons that touch or overlap themselves. +The fabricated board may not look the way you expect if you violate this +principle. It is always ok to have two (or more) polygons touch or overlap +each other, but not for points within the same polygon to do so. + +

            The great advantage to this new polygon behavior is that simple or complex ground +and/or power planes can be easily made with polygons and seen on the screen. +If you don't want this auto-clearance behavior, or you load a layout created by +an early version of pcb-rnd, the old behavior +(shorts to all piercing pins and vias) is available. A ‘ChangeSize’ +operation (S key) toggles a polygon between the new and old polygon/pin +behavior. + +

            + +


            +Next: , +Previous: Polygon Objects, +Up: Intro + +
            + +

            2.8 Text

            + +

            +Text objects should be used to label a layout or to put additional +information on the board. Elements have their ‘layout-name’ labels on the +silk-screen layer. If you are making a board without a silkscreen, +you can use copper text to label the elements, but you have to do +this manually. + +

            Text is always horizontal when first created, but the +rotate mode can align it along 0, 90, 180 and 270 degree angles. +Text on the far side of the board will automatically appear mirror-imaged. + +

            Warning: TEXT OBJECTS ON A COPPER LAYER CREATE COPPER LINES BUT THEY ARE NOT SCANNED FOR +CONNECTIONS OR TESTED FOR CREATING SHORTS VS. THE NETLIST. NEITHER ARE TEXT OBJECTS TESTED AGAINST ANY DESIGN RULES. + +

            + +


            +Previous: Text Objects, +Up: Intro + +
            + +

            2.9 Nets

            + +

            +Layout files also contain the netlist that describes how the elements +are supposed to be interconnected. This list of connections can be +loaded from a netlist file (see Netlist File), or +entered by drawing rat-lines as described +previously. Each net has a name and routing style associated with it. +The net contains a list of all element layout-name names and +pin numbers that should +be connected to the net. Loading a netlist file will replace all +existing nets with the ones from the file. +The Netlist window provides an easy way to +browse through the net list. You can display the rat's-nest by selecting +‘optimize rats-nest’ from the Connects menu. If you move or rotate elements, +the rat's-nest will automatically follow the movements, but they won't +necessarily show the shortest paths until you optimize them again. + + +

            + +


            +Next: , +Previous: Intro, +Up: Top + +
            + +

            3 Getting Started

            + +

            +The goal of this chapter is to give you enough information to learn how +pcb-rnd works and how to develop your layouts to make the best use of pcb-rnd's +features. All event translations (i.e. the buttons and keys you +press) refer to the default application resource file shipped with pcb-rnd. +There is probably no need to change this unless your window +manager uses some of the button events itself; however, if you want +to customize the behavior of pcb-rnd then changing the resource file +is usually the best way to do it. + +

            Get yourself a printout of this chapter and User Commands, if you +haven't already done so, and follow the examples. + +

            Start pcb-rnd (the actual command will use all lower-case letters) +without any additional options. + +For error messages on startup, see problems. +

            + +

            + +
            + +


            +Next: , +Up: Getting Started + +
            + +

            3.1 The Application Window

            + +

            The main window consists of five areas: the menu bar at the top, the toolbar +below the menu bar, the layer controls along the left, the layout area to the +right of the layer controls, and the status line at the bottom of the window. + +

            + +
            + +


            +Next: , +Up: Application Window + +
            + +

            3.1.1 Menus

            + +

            +The menus are located at the top of the Layout area. Most, but not all, +of their functions are also available from the keyboard. Similarly, some +functions are only achievable through the keyboard or command entry. +Some menu entries such as ‘center layout’ in the Screen menu require a certain cross hair position. +In this case a prompt message will popup at the bottom of the screen +with wording similar to the following: +

                 move pointer to the appropriate screen position and press a button
            +
            +

            Any mouse button will do the job, whereas any key except the arrow (cursor) keys +will cancel the operation. If it seems like the menu hasn't done what you +expected, check to see if it is waiting for the position click. For details see Actions. + +

            Pressing Btn3 in the Layout area also pops up a menu with many of the most common operations (except +when you're in the midst of drawing a line or arc). When +a choice in the Btn3 popup menu needs a cross hair position, it uses the position +where the cross hair was when Btn3 was pressed. For example, to get detailed +information on an object, place the cross hair over the object, press Btn3, then +choose ‘object report’. If you pop up the Btn3 menu but don't want to +take any of the actions, click on one of the headers in the menu. + + + +

            File
            This menu offers a choice of loading, saving and printing data, saving +connection information to a file or quitting the application. Most +of the entries in the File menu are self explanatory. +Selecting +‘print layout’ pops up a printer control dialog. +A selection of several device drivers is available from the printer control +dialog. Presently PostScript, encapsulated PostScript, +and GerberX are supported. The GerberX driver produces +all of the files necessary to have the board professionally manufactured. +The connection saving features in the File menu produce outputs in an +arcane format that is not too useful. They do not produce netlist +files. + +

            + +

            Edit + +
            The Edit menu + provides the usual cut, copy, paste which work on selections. To learn how + to create complex selections, see Arrow Tool. + The Edit menu also provides access to Undo and Redo of the last + operation. These can also be accomplished with the U key and + Shift-R key. Finally, the Edit menu allows you to change + the names of: the layout, the active layer, or text objects on the layout. + +

            + + + +
            + +


            Settings
            The Settings menu controls several operating configuration +parameters. The ‘edit layer groups’ entry brings up a dialog +that allows you to change the way layers are grouped. Layer grouping +is described in Layer Objects. The ‘all-direction lines’ +entry controls +the clipping of lines to 45-degree angles. You can also control +whether moving individual objects causes the attached lines to +"rubber band" with the move or not from the Settings menu. Another +entry controls whether the starting clip angle for the two-line +mode (see Line Objects) alternates every other line. You can +also control whether element names must be unique from the Settings +menu. When unique element names are enforced, copying a new element +will automatically create a unique ‘layout-name’ name for it +provided that the name originally ended with a digit (e.g. +U7 or R6). The Settings menu allows you to control +whether the cross hair will snap to pins and pads even when they +are off-grid. Finally you can control whether new lines and +arcs touch or clear intersecting polygons from this menu. + +


            Select
            This menu covers most of the operations that work with selected objects. +You may either (un)select all visible objects on a layout or only the ones +which have been found by the last connection scan see + + +. +You can delete all selected objects from this menu. +Other entries in the Select menu change the sizes of selected objects. +Note that a select action only affects those objects that are +selected and have their visibility turned on in the Layer Control +panel. The Select menu also provides a means for selecting objects +by name using unix Regular Expressions. + +


            Buffer
            From the Buffer menu you may select one out of five +buffers to use, rotate or clear its contents or save the buffer contents +to a file. You can also use the ‘break buffer element to pieces’ entry +to de-compose an element into pieces for editing. +Note: only objects with visibility turned on are pasted to the layout. If +you have something in a buffer, then change which side of the board you +are viewing, the contents of the buffer will automatically be mirrored +for pasting on the side you are viewing. It is not necessary to clear +a buffer before cutting or copying something into it - it will automatically +be cleared first. + +


            Connects
            The entries available through the Connects menu allow you to find +connections from objects and to manipulate these. +You can also optimize or erase rat's nests from this menu. Finally, +the ‘auto-route all rats’ entry allows you to auto-route +all connections show by the rat's nest. The auto-router will use +any visible copper layer for routing, so turn off the visibility of any +layers you don't want it to use. The auto-router will automatically +understand and avoid any traces that are already on the board, but +it is not restricted to the grid. Finally, +the auto-router routes using the active sizes (except for nets that +have a route-style defined). pcb-rnd always knows which tracks +were routed by the auto-router, and you can selectively remove them +without fear of changing tracks that you have manually routed +with the ‘rip-up all auto-routed tracks’ entry in the Connects +menu. The ‘design rule checker’ entry runs a check for copper +areas that are too close together, or connections that touch too +tenuously for reliable production. The DRC stops when the first +problem is encountered so after fixing a problem be sure to +run it again until no problems are found. +
                      Warning: COPPER TEXT IS IGNORED BY THE DRC CHECKER. 
            + +


            Plugins
            The Plugins allows the user to + manage pcb-rnd's plugins. + +


            Info
            The ‘generate object report’ entry from the Info menu +provides a way to get detailed information +about an object, such as its coordinates, dimensions, etc. +You can also get a report summarizing all of the drills +used on the board with ‘generate drill summary’. Lastly, +you can get a list of all pins, pads and vias that were +found during a connection search. + +


            Window
            The Window menu provides a way to bring each of pcb-rnd's +windows to the front. The Library window is used to +bring elements from the library into the paste-buffer. The +Message Log window holds the various messages that +pcb-rnd sends to the user. The Netlist window shows +the list of connections desired. + +
            + +

            Now that you're familiar with the various menus, it's time +to try some things out. From the File menu choose +‘load layout’, navigate to the tutorial folder, then +load the file ‘tut1.pcb’. + +

            + +


            +Next: , +Previous: Menu, +Up: Application Window + +
            + +

            3.1.2 The Tool Selectors

            + +

            +The tool selector buttons reside below the layer controls. +They are used to select which layout tool to use in the drawing +area. Each tool performs its function when Btn1 is pressed. +Every tool gives the cursor a unique shape that identifies it. +The tool selector buttons themselves are icons that illustrate their function. +Each layout tool can also be selected from the keyboard: +

                     F1 key       Via tool
            +         F2 key       Line tool
            +         F3 key       Arc tool
            +         F4 key       Text tool
            +         F5 key       Rectangle tool
            +         F6 key       Polygon tool
            +         F7 key       Buffer tool
            +         F8 key       Delete tool
            +         F9 key       Rotate tool
            +         Insert key   Insert-point tool
            +         F10 key      Thermal tool
            +         F11 key      Arrow tool
            +         F12 key      Lock tool
            +
            +

            Some of the tools are very simple, such as the Via tool. Clicking +Btn1 with the Via tool creates a via at the cross hair position. +The via will have the diameter and drill sizes that are active, +as shown in the status line. +The Buffer tool is similar. With it, <Btn1> copies +the contents of the active buffer to the layout, but only +those parts that reside on visible layers are copied. +The Rotate tool allows you to rotate elements, arcs, and text objects +90 degrees counter-clockwise with each click. Holding the Shift +key down changes the Rotate tool to clockwise operation. +Anything including groups of objects +can be rotated inside a buffer using the rotate buffer menu option. + +

            The Line tool is explained in detail in Line Objects. Go read +that section if you haven't already. +Activate the Line tool. Set the active layer to the solder layer. +Try drawing some lines. Use the U key to undo some of the +lines you just created. Zoom in a bit closer with the Z key. +Draw some more lines. Be sure to draw some separate lines by starting +a new anchor point with Ctrl-Btn1. Change the ‘crosshair snaps to pin/pads’ +behavior in the Settings menu. Now draw a line. Notice that +the new line points must now always be on a grid point. It might not +be able to reach some pins or pads with this setting. Increase the active line thickness +by pressing the L key. Note that the status line updates +to reflect the new active line thickness. Now draw another line. Before completing the +next line, make the component layer active by pressing the 4 key. +Now finish the line. Notice that a via was automatically placed where +you switched layers. pcb-rnd does not do any checks to make sure that +the via could safely be placed there. Neither does it interfere with +your desire to place lines haphazardly. It is up to you to place +things properly when doing manual routing with the Line tool. + +

            The Arc tool is explained in detail in Arc Objects. Its +use is very similar to the Line tool. + +

            The Rectangle tool, Polygon tool and Thermal tool are explained in detail in +Polygon Objects. Go read that section. +Remember that the Thermal tool will only create and destroy thermals +to polygons on the active layer. Use the Rectangle tool to make a +small copper plane on the component layer. Now place a via in the +middle of the plane. Notice that it does not touch the plane, and +they are not electrically connected. Use the Thermal tool to make +the via connect to the plane. Thermals allow the via or pin to +be heated by a soldering iron without having to heat the entire +plane. If solid connections were made to the plane, it could be +nearly impossible to solder. Shift-click on the via with the Thermal +tool to change the style of thermal used or to make the connection +solid. Click on the via again with the Thermal tool to remove the +connection to the plane. + +

            The Insert-point tool is an editing tool that allows you to add +points into lines and polygons. The +Insert-point tool enforces the 45 degree line +rule. You can force only the shorter line segment to 45 +degrees by holding the Shift key down while inserting the point. +Try adding a point into one of the lines you created. Since line +clipping is turned on, you may need to move the cross hair quite far +from the point where you first clicked on the line. Turn off the +line clipping by selecting ‘all-direction lines’ from the +Settings menu (or hit +the Period key). Now you can place an inserted point anywhere. +Try adding a point to the rectangle you made earlier. Start by clicking +somewhere along an edge of the rectangle, then move the pointer to +a new location and click again. + +

            The delete-mode deletes the object beneath the cursor with each +Btn1 click. +If you click at an end-point that two lines have in common, it will replace the two lines with a single line +spanning the two remaining points. This can be used to delete an "inserted" +point in a line, restoring the previous line. Now delete one of the original corner +points of the polygon you were just playing with. To do this, place the cross hair over the +corner and click on it with the Delete tool. You could also use the Backspace key +if some other tool is active. Try deleting some of +the lines and intermediate points that you created earlier. Use undo +repeatedly to undo all the changes that you've made. Use redo +a few times to see what happens. Now add a new line. Notice that +you can no longer use redo since the layout has changed since +the last undo happened. The undo/redo tree is always pruned in this +way (i.e. it has a root, but no branches). + +

            The Arrow tool is so important, it has its own section: Arrow Tool. +Go read it now. + +

            The Lock tool allows you to lock objects on the layout. When an object +is locked, it can't be selected, moved, rotated, or resized. This is +useful for very large objects like ground planes, or board-outlines that +are defined as an element. With such large objects, nearly anywhere you +click with the Arrow tool will be on the large object, so it could be +hard to draw box selections. If you lock an object, the Arrow tool will +behave as if it didn't exist. You cannot unlock an object with undo. +You must click on it again with the Lock tool. If an object is locked, +previous changes to it cannot be undone either. When you lock +an object, a report message about it is popped up and will always tell +you what object it is, and that it is locked if you just locked it. +Other than noticing your inability to manipulate something, the only +way to tell an object is locked is with a report from the Info +menu. Use the Lock tool sparingly. + + +

            + +


            +Next: , +Previous: Layer Controls, +Up: Application Window + +
            + +

            3.1.3 The Layer Controls

            + +

            +The layer control panel, located in the upper left, is used to turn on +and off the display of layer groups and to select the active drawing layer. +If a layer hasn't been named, the label "(unknown)" is used as the default. +If this happens, it probably means the application resources are not installed +properly. + +

            The upper buttons are used to switch layers on and off. Click +<Btn1> on one or more of them. Each click toggles the setting. +If you turn off the currently active layer, another one that is visible +will become active. If there are no others visible, you will not be +able to turn off the active layer. +When the layers are grouped, clicking on these buttons will toggle +the visibility of all layers in the same group. This is a good idea because +layers in the same group reside on the same physical layer of +the actual board. Notice that this example has 2 groups each having +3 layers, plus two other layers named ‘unused’. +Use the ‘Edit layer groups’ option in the ‘Settings’ menu to +change the layer groupings in the lesstif GUI or the ‘Preferences’ +dialog from the ‘File’ menu in the GTK+ GUI. Note that changing the +groupings can radically alter the connectivity on the board. +Grouping layers is only useful for helping you to color-code +signals in your layout. Note that grouping layers actually reduces the number +of different physical layers available for your board, so to make an eight +layer board, you cannot group any layers. + +

            The far side button turns on and off the visibility of elements +(including SMD pads) on the opposite (to the side you're viewing) +board side, as well as silk screening on that side. It does not +hide the x-ray view of the other copper layers, these must be turned off +separately if desired. Use the tab key to view the entire board from the other +side. To see a view of what the back side of the board will actually look like, +make the solder layer the active layer then press tab until the status +line says "solder" on the right, then turn off the visibility of all layers +except solder, pins/pads, vias, and silk. Now turn them all back on. + +

            The lowest button, named active, is used to change the active +drawing layer. Pressing <Btn1> on it pops up a menu to select which +layer should be active. +Each entry is labeled with the layer's name and drawn in its color. +The active layer is automatically made visible. The active layer is +always drawn on top of the other layers, so the ordering of layers +on the screen does not generally reflect the ordering of the manufactured +board. Only the solder, component, silkscreen, and solder-mask layers +are always drawn in their physical order. Bringing the active layer +to the top makes it easier to select and change objects on the active layer. +Try changing the active layer's name to ABC by selecting +‘edit name of active layer’ from the ‘Edit’ menu. +Changing the active layer can also be done by pressing keys +1..MAX_LAYER. + +

            Turn off the visibility of the component layer. +Now make the component layer the active layer. Notice that it +automatically became visible. Try setting a few +other layers as the active layer. You should also experiment +with turning on and off each of the layers to see what happens. + +

            The netlist layer is a special layer for adding connections to +the netlist by drawing rat lines. This is not the recommended +way to add to the netlist, but occasionally may be convenient. +To learn how to use the netlist layer see Net Objects. + + + +

            + +

            3.1.4 Layout Area

            + +

            +The layout area is where you see the layout. The cursor shape depends +on the active tool when the pointer is moved into the layout area. +A cross hair follows the mouse pointer with respect to the grid setting. +Select a new grid from the Screen menu. +The new value is updated in the status line. +A different way to change the grid is +Shift<Key>g to decrease or <Key>g to increase +it, but this only works for English (integer mil) grids. +The grid setting is saved along with the data when you save a pcb layout. +For homemade layouts a value around 50 is a good setting. +The cursor can also be moved in the layout area with the cursor (arrow) keys or, for larger +distances, by pressing the Shift modifier together with a cursor key. + +

            + + +


            +Previous: Layout Area, +Up: Application Window +
            + +

            3.1.5 The Status-line and Input-field

            + +

            +The status-line is located at the bottom edge of the main window. +During normal operation the status information is visible there. +When a selected menu operation requires an additional button click, the +status-line is replaced by a message telling you to position the cursor +and click. +When a text input is required, the status-line is replaced by the +Input-field which has a prompt for typing the input. + +

            The status-line shows, from left to right, the side of the board that you +are viewing (Tab key changes this), the current grid values, +if new lines are restricted to 45 degrees, +which type of 45 degree line mode is active, whether rubberband move and +rotate mode is on (R), and the zoom factor. +This information is followed by the active line-width, via-size +and drilling hole, keepaway spacing, and text scaling. Last is the active buffer number and the +name of the layout. An asterisk appearing at the far left indicates that the +layout has been modified since the last save. +Note that the name of the layout is not the same +thing as the filename of the layout. +Change the grid factor to 1.0 mm from the Screen menu. Observe how the +status line shows the new grid setting. Except for the case of the metric +grid, all dimensions in the status line are in units of 0.001 inch (1 mil). + +

            The input-field pops up (temporarily replacing the status-line) whenever user input +is required. Two keys are bound to the input field: the Escape key +aborts the input, Return accepts it. Let's change the name of a component +on the board to see how the input-field works. Position the cross hair over +R5, and press the N key. The input field pops-up showing the name +for you to edit. Go ahead and change the name, then hit return. Notice the name +of the element changed. Now undo the change by pressing the U key. You can +position the cross hair over the name, or the element before pressing the +N key. + +

            Now select ‘realign grid’ from the Screen menu. Notice that the +status line has been replaced with an instruction to position the cursor +where you want a grid point to fall. In this case, since the cross hair +can only fall on a grid point, you must move the tip of the finger cursor +to the place where you want a grid point to appear. Do not worry that +the cross hair is not coincident with the cursor. Click Btn1 at +your chosen location. See how the grid has shifted, and the status line +has returned. + +

            The present cross hair position is displayed in the upper right corner of the window. +Normally this position is an absolute coordinate, but you can anchor a marker at +the cross hair location by pressing Ctrl-M (try it now) and then the +display will read both the absolute cross hair position as well as the difference +between it and the marker. The numbers enclosed in < > are the X and Y distances +between the cross hair and the mark, while the numbers enclosed in parenthesis +are the distance and angle from the mark to the cross hair. The values displayed +are always in units of 0.001 inch (1 mil). +Pressing Ctrl-M again turns the marker off. + +

            + +


            +Next: , +Previous: Status-line and Input-field, +Up: Getting Started + +
            +

            3.2 Log Window

            + +

            +This optional window is used to display all kind of messages including +the ones written to stderr by external commands. The main advantage +of using it is +that its contents are saved in a scrolling list until the +program exits. Disabling this feature by setting the resource +useLogWindow to false will generate popup windows to display +messages. The stderr of external commands will appear on pcb-rnds +stderr which normally is the parent shell. I suggest you iconify +the log window after startup for example by setting *log.iconic to +true in the resource file. If raiseLogWindow is set true, +the window will deiconify and raise itself whenever new messages are to be +displayed. + +

            + +


            +Next: , +Previous: Log Window, +Up: Getting Started + +
            + +

            3.3 Library Window

            + +

            +The library window makes loading elements (or even partial layouts) easy. +Just click the appropriate library from the list on the left. A list +of its elements then appears on the right. Select an element +from the list by clicking on its description. Selecting an element from the +library will also automatically copy the element into +the active buffer, then invoke the Buffer tool so +you can paste it to the layout. Elements in the old library should be +taken with a grain of salt (i.e. check them carefully before +using). The old library names all begin with ~ so you can easily distinguish between +the old and new libraries. All of the elements in the new library +should be thoroughly vetted, so you +can use them with confidence. The new libraries are stored simply +as directories full of element files, so making additions to the +new library is easy since there is no need to learn m4. +For details on the old libraries, +check-out Library File and Library Contents File. For +details on the format of an element file used for the new libraries, +see Element File. + +

            + +


            +Next: , +Previous: Library Window, +Up: Getting Started + +
            + +

            3.4 Netlist Window

            + +

            +The netlist window is very similar to the library window. On the left +is a list of all of the nets, on the right is the list of connections +belonging to the chosen net. The chosen net is highlighted in the +list and also shown on the second line of the window in red. If the +net name has a star to the left of it then it is "disabled". A disabled +net is treated as if it were not in the net list. This is useful, for +example, if you plan to use a ground plane and don't want the ground +net showing up in the rat's nest. You can enable/disable individual +nets by double-clicking the net name. If you want to enable or disable +all nets at once, there are two buttons at the top of the netlist +window for this purpose. + +

            The button labeled ‘Sel Net On Layout’ +can be used to select (on the layout) everything that is connected +(or is supposed to be connected) to the net. If you click on a +connection in the connection list, it will select/deselect +the corresponding pin or pad in the layout and also center the layout +window where it is located. If you "Find" (‘lookup connection +to object’ in the Connects menu [also F key]), a pin +or pad it will also choose the net and connection in the netlist window +if it exists in the netlist. + +

            If no netlist exists for the layout, then the netlist window does not +appear. You can load a netlist from a file from the File menu. The +format for netlist files is described in Netlist File. + +

            + +


            +Next: , +Previous: Netlist Window, +Up: Getting Started + +
            + +

            3.5 Drawing and Removing Basic Objects

            + +

            +hace begging gutting here, and do a real-world tutorial example. + +

            There are several ways of creating new objects: you can draw them yourself, +you can copy an existing object (or selection), or you can load an element from a file or +from the Library window. Each type of object has a particular tool for creating it. + +

            The active tool can be selected from the tool selectors in the bottom +left corner or by one of the function keys listed earlier in this chapter. +Each <Btn1> press with the tool tells the application to create +or change the appropriate object or at least take +the first step to do so. Each tools causes the cursor to take +on a unique shape and also causes the corresponding +tool selector button to be highlighted. You can use either cue +to see which tool is active. + +

            Insert mode provides the capability of inserting new points into existing +polygons or lines. The 45 degree line clipping is now enforced when selected. +Press and hold the shift key while positioning the new point to only clip +the line segment to the nearer of the two existing points to 45 degrees. +You can also toggle the 45-degree clipping in the middle of a point +insertion by pressing the <Key>. +If the shift key is not depressed and the 45 degree line clipping mode +is on, both new line segments must be on 45 degree angles - greatly +restricting where the new point may be placed. In some cases this can cause +confusion as to whether an insertion has been started since the two new +lines may be forced to lie parallel on top of the original line until the +pointer is moved far from the end points. + +

            Removing objects, changing their size or moving them only applies to objects +that are visible when the command is executed. + +

            + +
            + +


            +Next: , +Up: Drawing and Removing + +
            + +

            3.5.1 Common Drawing and Removing Methods

            + +

            +There are several keystrokes and button events referring to an object +without identifying its type. Here's a list of them: + +

            <Btn1> creates (or deletes) an object depending on the +current mode. + +

            <Key>BackSpace or <Key>Delete removes the visible +object at the cursor location. When more than one object exists at the +location, the order of removal is: via, line, text, polygon and +element. The drawn layer order also affects the search - whatever is +top - most (except elements) is affected before lower items. Basically +all this means that what is removed is probably just what you expect. +If for some reason it isn't, undo and try again. +Only one object is removed for each keystroke. If two or more +of the same type match, the newest one is removed. + +

            Use <Key>s and Shift<Key>s to change the size (width) +of lines, arcs, text objects, pins, pads and vias, or to toggle the style +of polygons (whether pins and vias automatically have clearances). + +

            <Key>n changes the name of pins, pads, vias, the +string of a text object, or the currently displayed label of an element. + +

            <Key>m moves the line, arc, or polygon under the cross hair to the +active layer if it wasn't on that layer already. + +

            <Key>u (undo) recovers from an unlimited number of operations +such as creating, removing, moving, copying, selecting etc. It works like +you'd expect even if you're in the midst of creating something. + +

            Shift<Key>r restores the last undone operation provided no other +changes have been made since the undo was performed. + +

            <Key>tab changes the board side you are viewing. + +

            For a complete list of keystrokes and button events see Translations. + +

            + +


            +Next: , +Previous: Common, +Up: Drawing and Removing + +
            + +

            3.5.2 Lines

            + +

            +To draw new lines you have to be in line-mode. Get there either by +selecting it from the Tool palette or by pressing <Key>F2. +Each successive notify event creates a new line. The +adjustment to 45 degree lines is done automatically if it is selected from the +Display menu. You can toggle the 45 degree mode setting by +pressing the <Key>. (That is the period key). When 45 degree enforcement +is turned on there are three distinct modes of line creation: a single +line on the closest 45 degree vector towards the cross hair (but not necessarily +actually ending at the cross hair), two lines created such that the first leaves +the start point on a 90 degree vector and the second arrives at the cross hair +on a 45 degree vector, and finally two lines created such that the first leaves +the start point on a 45 degree vector and the second arrives at the cross hair +on a 90 degree vector. These last two modes always connect all the way from +the start and end points, and all lines have angles in 45 degree multiples. +The <Key>/ cycles through the three modes. The status line shows a +text icon to indicate which of the modes is active and the lines following +the cross hair motion show the outline of the line(s) that will actually be created. +Press <Key>Escape to leave line-mode. + +

            <Key>l, Shift<Key>l and the entries in the +Sizes menu change the initial width of new lines. This width is also +displayed in the status line. + +

            + +


            +Next: , +Previous: Lines, +Up: Drawing and Removing + +
            + +

            3.5.3 Arcs

            + +

            +An Arc is drawn with the arc-tool. Get there either by selecting it +from the Tool palette or by pressing <Key>F8. Press Btn1 to +define the starting point for the arc. Drag the mouse towards the desired +end point along the path you want the arc to follow. The outline of the arc that +will be created is shown on the screen as you move the mouse. Arcs are always +forced to be 90 degrees and have symmetrical length and width ( i.e. they are +a quarter circle). The next Btn1 click creates the arc. It will have +the same width as new lines (displayed in the status line) and appear on the +active layer. The arc leaves the starting point towards the cross hair along +the axis whose distance from the cross hair is largest. Normally this means that +if you drag along the path you want the arc to follow, you'll get what you +want. If the grid is set to the arc radius, then the two distances will be +equal and you won't be able to get all of the possible directions. If this +is thwarting your desires, reduce the grid spacing (!Shift<Key>G) and +try again. + +

            + +


            +Next: , +Previous: Arcs, +Up: Drawing and Removing + +
            + +

            3.5.4 Polygons and Rectangles

            + +

            +A polygon is drawn by defining all of its segments as a series of +consecutive line segments. If the first point matches a new one and if +the number of points is greater than two, then the polygon is closed. +Since matching up with the first point may be difficult, you may use +Shift<Key>p to close the polygon. The Shift<Key>p won't +work if clipping to 45 degree lines is selected +and the final segment cannot match this condition. +I suggest you create simple convex polygons in order to avoid a strong +negative impact on the performance of the connection scanning routines. +The rectangle-mode is just an easy way to generate rectangular polygons. +Polygon-mode also is selected by <Key>F6 whereas +rectangle-mode uses <Key>F4. +Pressing a <Btn1> at two locations creates a rectangle by +defining two of its corners. +<Key>Insert brings you to insert-point-mode which lets you +add additional points to an already existing polygon. +Single points may be removed by moving the cross hair to them and selecting +one of the delete actions (remove-mode, BackSpace, or Delete. This only works +if the remaining polygon will still have three or more corners. +Pressing <Key>u or <Key>p while entering a new polygon +brings you back to the previous corner. Removing a point does not +force clipping to 45 degree angles (because it's not generally possible). +Newly created polygons will not connect to pins or vias +that pierce it unless you create a thermal (using the thermal mode) to make +the connection. If the edge of a polygon gets too close to a pin or via that +lies outside of it, a warning will be issued and the pin will be given a +special color. Increasing the distance between them will remove the warning +color. + +

            + +


            +Next: , +Previous: Polygons, +Up: Drawing and Removing + +
            + +

            3.5.5 Text

            + +

            +Pressing <Key>F5 or clicking one of the text selector buttons +changes to text-mode. +Each successive notify event (<Btn1>) +pops up the input line at the bottom and queries for a string. +Enter it and press <Key>Return to confirm or +<Key>Escape to abort. +The text object is created with its upper left corner at the current pointer +location. +The initial scaling is changed by <Key>t and +Shift<Key>t or from the Sizes menu. + +

            Now switch to rotate-mode and press +<Btn1> at the text-objects location. Text objects +on the solder side of the layout are automatically mirrored and +flipped so that they are seen correctly when viewing the solder-side. + +

            Use <Key>n to edit the string. + +

            TEXT OBJECTS ON COPPER LAYERS CREATE COPPER LINES BUT THEY ARE NOT SCANNED FOR +CONNECTIONS. If they are moved to the silkscreen layer, they +no longer create copper. + +

            + +


            +Next: , +Previous: Text, +Up: Drawing and Removing + +
            + +

            3.5.6 Vias

            + +

            +The initial size of new vias may be changed by <Key>v and +Shift<Key>v or by selecting the appropriate entry from the +Sizes menu. Mod1<Key>v and Mod1 Shift<Key>v do +the same for the drilling hole of the via. +The statusline is updated with the new values. +Creating a via is similar to the other objects. Switch to via-mode +by using either the selector button or <Key>F1 then press +<Key>] or <Btn1> to create one. +<Key>n changes the name of a via. If you want to create a mounting +hole for your board, then you can place a via where you want the hole to +be then convert the via into a hole. The conversion is done by pressing +!Ctrl<Key>h with the cross hair over the via. Conceptually it is +still a via, but it has no copper annulus. If you create such a hole in +the middle of two polygons on different layers, it will short the layers. +Theoretically you could arrange for such a hole not to be plated, but a +metal screw inserted in the hole would still risk shorting the layers. +A good rule is to realize that holes in the board really are vias between +the layers and so place them where they won't interfere with connectivity. +You can convert a hole back into a normal via with the same keystroke used +to convert it in the first place. + +

            + +


            +Next: , +Previous: Vias, +Up: Drawing and Removing + +
            + +

            3.5.7 Elements

            + +

            +Some of the functions related to elements only work if both the package +layer and the pin layer are switched on. + +

            Now that you're familiar with many of the basic commands, it is +time to put the first element on the layout. +First of all, you have to load data into the paste buffer. +There are four ways to do this: +

                    1) load the data from a library
            +        2) load the data from a file
            +        3) copy data from an already existing element
            +        4) convert objects in the buffer into an element
            +
            +

            We don't have any elements on the screen yet nor anything in the +buffer, so we use number one. + +

            Select lsi from the menu in the library window press +<Btn1> twice at the appropriate text-line to get +the MC68030 CPU. +The data is loaded and the mode is switched to pastebuffer-mode. +Each notify event now creates one of these beasts. Leave the mode +by selecting a different one or by <Key>Escape which resets +all modes.. +The cross hair is located at the mark position as defined by +the data file. Rotating the buffer contents is done by selecting +the rotate entry of the Buffer menu or by pressing +Shift<Key>F3. The contents of the buffer +are valid until new data is loaded into it either by a cut-to-buffer +operation, copy-to-buffer operation or by loading a new data file. +There are 5 buffers +available (possibly more or less if changed at compile time +with the MAX_BUFFER variable in globalconfig.h). +Switching between them is done by selecting a menu entry or +by Shift<Key>1..MAX_BUFFER. +Each of the two board sides has its own buffers. + +

            The release includes all data files for the circuits that are used +by the demo layout. The elements in the LED example are not found in the library, +but you can lift them from the example itself if you want. +If you have problems with the color of the cross hair, change the resource +cross hairColor setting to a different one. + +

            Now load a second circuit, the MC68882 FPU for example. +Create the circuit as explained above. You now have two different unnamed +elements. Unnamed means that the layout-name of the element +hasn't been set yet. Selecting description from the Display +menu displays the description string of the two circuits which +are CPU and FPU. The values of the circuits are set to MC68030 and MC68882. +Each of the names of an element may be changed +by <Key>n at the elements location and editing the old name in +the bottom input line. Naming pins and vias is similar to elements. +You can hide the element name so that it won't appear on the board +silkscreen by pressing <key>h with the cursor over the element. +Doing so again un-hides the element name. + +

            Entering :le and selecting an element data file is +the second way to load circuits. + +

            The third way to create a new element is to copy an existing one. +Please refer to Moving and Copying. + +

            The fourth way to create a new element is to convert a buffer's contents +into an element. Here's how it's done: Select the Via-tool from the +Tool pallet. Set the grid spacing to something appropriate for +the element pin spacing. Now create a series of vias where the pins +go. Create them in pin number order. It is often handy to place a reference +point (!Ctrl<Key>m) in the center of the first pin in order to measure +the location of the other pins. Next make a solder-side layer the active +layer from the active-layer popup menu. Now draw the outline of +the element using lines and arcs. When you're done, select everything that +makes up the element with a box selection (<Btn3Down> drag, +<Btn3Up>). Now select "cut selection to buffer" from the Buffer +menu. Position the cursor over the center of pin 1 and press the left +button to load the data into the buffer. +Finally select "convert buffer to element" from the Buffer menu. +You'll only want to create elements this way if they aren't already in the +library. It's also probably a good idea to do this before starting any of +the other aspects of a layout, but it isn't necessary. + +

            To display the pinout of a circuit move to it and press Shift<Key>d +or select show pinout from the Objects menu. A new window +pops up and displays the complete pinout of the element. This display can +be difficult to read if the component has been rotated 90 degrees :-( +therefore, the new window will show an un-rotated view so the pin names +are readable. +<Key>d displays the name of one or all pins/pads inside the +Layout area, this is only for display on-screen, it has no effect on any +printing of the layout. + +

            You also may want to change a pin's or pad's current size by pressing +<Key>s to increase or Shift<Key>s to decrease it. While +this is possible, it is not recommended since care was probably taken +to define the element structure in the first place. You can also change the thickness +of the element's silkscreen outline with the same keys. You can +change whether a pin or SMD pad is rounded or square with the <Key>q. +SMD pads should usually have squared ends. Finally, you can change whether +the non-square pins are round or octagonal with the !Ctrl<Key>o. + +

            SMD elements and silkscreen objects are drawn in the "invisible object" +color if they are located on the opposite side of the board. + +

            For information on element connections refer to Connection Lists. + +

            + +


            +Previous: Elements, +Up: Drawing and Removing + +
            + +

            3.5.8 Pastebuffer

            + +

            +The line-stack and element-buffer of former releases have been replaced +by 5 (possibly more or less if changed at compile time +with the MAX_BUFFER variable in globalconfig.h) +multi-purpose buffers that are selected by +Shift<Key>1..MAX_BUFFER. The status line shows which buffer is +the active one. +You may load data from a file or layout into them. +Cut-and-paste works too. +If you followed the instructions earlier in this chapter you should +now have several objects on the screen. Move the cross hair to one of them +and press <Btn3Down> to toggle its selection flag. (If you drag the +mouse while the button is down, a box selection will be attempted instead +of toggling the selection.) The object +is redrawn in a different color. You also may want to try +moving the pointer while holding the third button down and +release it on a different location. This selects all objects inside the +rectangle and unselects everything else. If you want to add a box selection +to an existing selection, drag with Mod1<Btn3Down> instead. +Dragging Shift Mod1<Btn3Down> unselects objects in a box. +Now change to pastebuffer-mode and select some operations from the +Buffer menu. Copying objects to the buffer is available as +Mod1<Key>c while cutting them uses Mod1<Key>x as +shortcut. Both clear the buffer before new data is added. +If you use the menu entries, you have to supply a cross hair position by +pressing a mouse button. The objects are attached to the pastebuffer +relative to that cross hair location. +Element data or PCB data may be merged into an existing layout by loading +the datafiles into the pastebuffer. Both operations are available from +the File menu or as user commands. + +

            + +


            +Next: , +Previous: Drawing and Removing, +Up: Getting Started + +
            + +

            3.6 Moving and Copying

            + +

            +All objects can be moved including element-names, by +<Btn2Down>, dragging the pointer while holding the button down +and releasing it at the new location of the object. If you use +Mod1<Btn2Down> instead, the object is copied. Copying does not work for +element-names of course. You can move all selected objects with +Shift <Btn1>. This uses the Pastebuffer, so +it will remove whatever was previously in the Pastebuffer. +Please refer to Pastebuffer. +If you want to give a small nudge to an object, but you don't think +that the mouse will give you the fine level of control that you want, +you can position the cursor over the object, press <Key>[, +move it with the arrow keys, then press <Key>] when it's at the +desired position. Remember that all movements are forced onto grid coordinates, so +you may want to change the grid spacing first. + +

            To move a trace or group of traces to a different layer, first select +the tracks to be moved. It's easiest to do this if you shut off everything +but that layer first (i.e. silk, pins, other layers, etc). +Now set the current layer to be the new layer. +Press Shift-M to move all the selected tracks to the current layer. +See the MoveToCurrentLayer action for more details. + +

            + +


            +Next: , +Previous: Moving and Copying, +Up: Getting Started + +
            + +

            3.7 Loading and Saving

            + +

            +After your first experience with pcb-rnd you will probably want to save +your work. :s name passes the data to an external program which +is responsible for saving it. For details see saveCommand in +Resources. +Saving also is available from the File menu, either with or +without supplying a filename. pcb-rnd reuses the last +filename if you do not pass a new one to the save routine. + +

            To load an existing layout either select load layout data from the +File menu or use :l filename. A file select box pops up if you +don't specify a filename. Merging existing layouts into the new one is +supported either by the File menu or by :m filename. + +

            pcb-rnd saves a backup of the current layout at a user specified interval. +The backup filename is created by appending a dash, "-", to the .pcb filename. +For example, if you are editing the layout in projects/board.pcb then the +backup file name will be projects/board.pcb-. If the layout is new and +has not been saved yet, then the backup file name is PCB.####.backup where the "####" +will be replaced by the process ID of the currenting running copy of pcb-rnd. +This default backup file name may be changed at compilation time via the +BACKUP_NAME +variable in globalconfig.h). During critical +sections of the program or when data would be lost it is saved as +PCB.%i.save. This file name may be changed at compile time +with the SAVE_NAME variable in globalconfig.h. + +

            + +


            +Next: , +Previous: Loading and Saving, +Up: Getting Started + +
            + +

            3.8 Printing

            + +

            +pcb-rnd now has support for device drivers, +PostScript, encapsulated PostScript, +and Gerber RS-274X drivers are +available so far. The Gerber RS-274X +driver additionally generates a numerical control (NC) drill file for +automated drilling, +a bill of materials file to assist in materials procurement and +inventory control, and a centroid (X-Y) file which includes the +centroid data needed +by automatic assembly (pick and place) machines. + I recommend the use of GhostScript if you +don't have a PostScript printer for handling the PostScript +output. Printing always generates +a complete set of files for a specified driver. +See the page about +the Print() action for additional information about the filenames. +The control panel offers a number of options. Most of them are not available +for Gerber output because it wouldn't make sense, for example, to scale the gerber output +(you'd get an incorrectly made board!) The options are: + + + + +

            device
            The top menu button selects from the available device drivers. + +


            rotate
            Rotate layout 90 degrees counter-clockwise before printing (default). + +


            mirror
            Mirror layout before printing. Use this option depending +on your production line. + +


            color
            Created colored output. All colors will be converted to black if this option +is inactive. + +


            outline
            Add a board outline to the output file. The size is determined by the +maximum board size changeable from the sizes menu. The outline appears +on the top and bottom sides of the board, but not on the internal layers. +An outline can be useful for determining where to shear the board from the +panel, but be aware that it creates a copper line. Thus it has the potential +to cause short circuits if you don't leave enough room from your wiring +to the board edge. Use a viewer to see what the output outline looks like +if you want to know what it looks like. + +


            alignment
            Additional alignment targets are added to the output. The distances between +the board outline is set by the resource alignmentDistance. Alignment +targets should only be used if you know for certain that YOU WILL BE USING +THEM YOURSELF. It is extremely unlikely that you will want to have alignment +targets if you send gerber files to a commercial pcb manufacture to be made. + +


            scaling
            It's quite useful to enlarge your printout for checking the layout. +Use the scrollbar to adjust the scaling factor to your needs. + +


            media
            Select the size of the output media from this menu. The user defined size +may be set by the resource media either from one of the well known +paper sizes or by a X11 geometry specification. +This entry is only available if you use X11R5 or later. +For earlier releases the user defined size or, if not available, A4 +is used. +Well known size are: +
                      	A3
            +          	A4
            +          	A5
            +          	letter
            +          	tabloid
            +          	ledger
            +          	legal
            +          	executive
            +
            +


            offset
            Adjust the offsets of the printout by using the panner at the right side +of the dialog box. +This entry is only available if you use X11R5 or later. A zero +offset is used for earlier releases. + +


            8.3 filenames
            Select this button to generate DOS compatible filenames for the output files. +The command input area will disappear if selected. + +


            commandline
            Use this line to enter a command (starts with |) or a filename. +A %f is replaced by the current filename. +The default is set by the resource printCommand. + +
            + +

            The created file includes some labels which are guaranteed to stay unchanged +

            +
            PCBMIN
            identifies the lowest x and y coordinates in mil. + +
            PCBMAX
            identifies the highest x and y coordinates in mil. + +
            PCBOFFSET
            is set to the x and y offset in mil. + +
            PCBSCALE
            is a floating point value which identifies the scaling factor. + +
            PCBSTARTDATA
            PCBENDDATA
            all layout data is included between these two marks. You may use them with an +awk script to produce several printouts on one piece of paper by +duplicating the code and putting some translate commands in front. +Note, the normal PostScript units are 1/72 inch. +
            + +
            + +


            +Next: , +Previous: Printing, +Up: Getting Started + +
            + +

            3.9 Exporting a layout

            + +

            +To export a layout choose Export layout from the File menu, then +select the desired exporter. + +

            + +
            + +


            +Next: , +Up: Exporting + +
            + +

            3.9.1 Bill of materials (bom)

            + +

            +Produces a bill of materials (BOM) file and a centroid (XY) file. + +

            + +


            +Next: , +Previous: bom, +Up: Exporting + +
            + +

            3.9.2 G-code (gcode)

            + +

            +The gcode exporter can generate RS274/NGC G-CODE files to be used with a CNC mill to +produce pcb's by mechanically removing copper from the perimeter of all elements. + +

            The elements are enlarged in order to compensate for the cutting tool size so +that the remaining copper corresponds to the original size; however all +polygons are left unchanged and will end up being a little smaller; this is not a +problem because the electrical connection is done with traces, which are correctly +enlarged. + +

            A .cnc file is generated for every copper layer, with the bottom layer mirrored so +that the milling is done right; of course it's not possible to produce directly +multi-layer (more than 2) pcb's with this method, but the cnc files for +intermediate layers are generated anyways. + +

            A drill file is also generated, and it contains all drills regardless of the hole +size; the drilling sequence is optimized in order to require the least amount of +movement. + +

            The export function generates an intermediate raster image before extracting the contour +of copper elements, and this image is saved as well (in .png format) for inspection. + +

            When the spacing between two elements is less than the tool diameter they will merge +and no isolation will be cut between them; the control image should be checked for +this behaviour. + +

            Possible workarounds are: increasing spacing, decreasing the tool size, increasing +the intermediate image resolution. + +

            To maximize the chance of producing correct pcb's it would be better to increase +the DRC clearance to at least the tool diameter and use traces as thick as possible; +the rule is: use the largest element that will not prevent the isolation cut. + +

            The exporter parameters are: + +

            +
            basename
            base name for generated files + +
            dpi
            intermediate image resolution; affects precision when extracting contours + +
            mill depth
            should be the copper depth + +
            safe z
            Z value when moving between polygons + +
            tool radius
            copper elements are enlarged by this amount + +
            drill depth
            depth of drills + +
            measurement unit
            for all parameters above, can be mm,um,inch,mil; g-code is always mm or inch +
            + +

            All .cnc files specify Z values as parameters, so that it's easy to +change them without the need to run the exporter again. + +

            Operation was verified with the EMC2 g-code interpreter. + +

            Following is a sample layout that is converted with default settings: +

            Sample Layout
            + +

            The control image shows that the spacing is sufficient: +

            Control Image
            + +

            The final tool path follows the perimeter of all elements: +

            Resulting Tool Path
            + +
            + +


            +Next: , +Previous: gcode, +Up: Exporting + +
            + +

            3.9.3 Gerber (gerber)

            + +

            +Produces RS274-X (a.k.a. gerber) photo plot files and Excellon drill files. + +

            + +


            +Next: , +Previous: gerber, +Up: Exporting + +
            + +

            3.9.4 Nelma (nelma)

            + +

            +Numerical analysis package export. + +

            + +


            +Next: , +Previous: nelma, +Up: Exporting + +
            + +

            3.9.5 Image (png)

            + +

            +Produces GIF/JPEG/PNG image files. + +

            + +


            +Next: , +Previous: png, +Up: Exporting + +
            + +

            3.9.6 Postscript (ps)

            + +

            +Export as postscript. +Can be later converted to pdf. + +

            + +


            +Previous: ps, +Up: Exporting + +
            + +

            3.9.7 Encapsulated Postscript (eps)

            + +

            +Export as eps (encapsulated postscript) for inclusion in other documents. +Can be later converted to pdf. + +

            + +


            +Next: , +Previous: Exporting, +Up: Getting Started + +
            + +

            3.10 Connection Lists

            + +

            +After completing parts of your layout you may want to check if all drawn +connections match the ones you have in mind. This is probably best done +in conjunction with a net-list file: see Rats Nest. +The following examples give more rudimentary ways to examine +the connections. +

                     1) create at least two elements and name them
            +         2) create some connections between their pins
            +         3) optionally add some vias and connections to them
            +
            +

            Now select lookup connection from the Connections menu, +move the cursor to a pin or via and press any mouse button. pcb-rnd +will look for all other pins and/or vias connected to the one you have +selected and display the objects in a different color. +Now try some of the reset options available from the same menu. + +

            There also is a way to scan all connections of one element. Select +a single element from the menu and press any button at the +element's location. All connections of this element will be saved +to the specified file. +Either the layout name of the element or its canonical name is used to +identify pins depending on the one which is displayed on the screen +(may be changed by Display menu). + +

            An automatic scan of all elements is initiated by choosing +all elements. It behaves in a similar fashion to scanning a single +element except the resource resetAfterElement +is used to determine if connections should be reset before a new element is +scanned. Doing so will produce very long lists because the power lines are +rescanned for every element. By default the resource is set to false +for this reason. + +

            To scan for unconnected pins select unused pins from the same +menu. + +

            + +


            +Next: , +Previous: Exporting, +Up: Getting Started + +
            + +

            3.11 Arrow Tool

            + +

            +Some commands mentioned earlier in this chapter also are able to operate on all +selected and visible objects. The Arrow tool is used to select/deselect +objects and also to move objects or selections. If you click and release +on an object with the Arrow tool, it will unselect everything else and +select the object. Selected objects change color to reflect that +they are selected. If you Shift click, it will add the object to +(or remove) the object from the existing selection. If you drag with +the mouse button down with the Arrow tool, one of several things could +happen: if you first pressed the button on a selected object, you +will be moving the selection to where you release the button. If you +first pressed the button on an unselected object, you will be moving +that object. If you first pressed the button over empty space, you +will be drawing a box to select everything inside the box. The Shift +key works the same way with box selections as it does with single objects. + +

            Moving a single un-selected object is different from moving a selection. +First of all, you can move the end of line, or a point in a polygon this +way which is impossible by moving selections. Secondly, if rubber banding +is turned on, moving a single object will rubber-band the attached lines. +Finally, it is faster to move a single object this way since there is no need +to select it first. + +

            You can select any visible object unless it is locked. If you select an +object, then turn off its visibility with the Layer controls, it won't +be moved if you move the remaining visible selection. + +

            If you have not configured to use strokes in the pcb-rnd user interface, then +the middle mouse button is automatically bound to the arrow tool, regardless +of the active tool (which is bound to the first mouse button). So using +the middle button any time is just like using the first mouse button +with the Arrow tool active. + +

            The entries of the Selection menu are hopefully self-explanatory. +Many of the Action Commands can take various key words that make +them function on all or some of the selected items. + +

            + +


            +Next: , +Previous: Arrow Tool, +Up: Getting Started + +
            + +

            3.12 Rats Nest

            + +

            +If you have a netlist that corresponds to the layout you are working on, you +can use the rats-nest feature to add rat-lines to the layout. +First you will need to load a netlist file (see :rn, +User Commands). +<Key>w adds rat-lines on the active layer using the current +line thickness shown in the status line (usually you'll want them to be thin lines). +Only those rat-lines that fill in missing connectivity (since you have +probably routed some connections already) are added. +If the layout is already completely wired, nothing will be added, and you will +get a message that the wiring is complete. + +

            Rat-lines are lines having the special property that they only connect to pins and +pads at their end points. Rat-lines may be drawn differently to other lines +to make them easier to identify since they have special behavior and cannot +remain in a completed layout. +Rat-lines are added in the minimum length straight-line tree pattern +(always ending on pins or pads) that satisfies the missing connectivity in the circuit. +Used in connection with moves and rotates of the elements, they are extremely useful for +deciding where to place elements on the board. The rat-lines will always automatically +rubberband to the elements whether or not the rubberband mode is on. The only way for +you to move them is by moving the parts they connect to. +This is because it is never desirable to have the rat-lines disconnected from +their element pins. Rat-lines will normally criss-cross +all over which gives rise to the name "rats nest" describing a layout connected with +them. If a SMD pad is unreachable on the active layer, a warning will be issued +about it and the rat-line to that pad will not be generated. + +

            A common way to use rats nests is to place some +elements on the board, add the rat-lines, and then use a series of moves/rotates of the +elements until the rats nest appears to have minimum tangling. You may want to iterate this step +several times. Don't worry if the layout looks messy - as long as you can get a sense for whether +the criss-crossing is better or worse as you move things, you're fine. +After moving some elements around, you may want to optimize the rats nest <Key>o +so that the lines are drawn between the closest points (this can change once you've moved components). +Adding rat-lines only to selected pads/pins (Shift<Key>w) +is often useful to layout a circuit a little bit at a time. +Sometimes you'll want to delete all the rat-lines (<Key>e) or +selected rat-lines (Shift<Key>e) in order to reduce confusion. +With a little practice you'll be able to achieve a near optimal component placement with +the use of a rats nest. + +

            Rat-lines are not only used for assisting your element placement, they can also help +you to route traces on the board. +Use the <Key>m to convert a rat-line under the cursor into +a normal line on the active layer. +Inserting a point into a rat-line will also cause the two new lines to be normal lines +on the board. +Another way that you can use rat-lines is to +use the <Key>f with the cursor over a pad or pin. All of the pins and +pads and rat-lines belonging to that net will be highlighted. This is a helpful way to +distinguish one net from the rest of the rats nest. You can then route those tracks, +turn off the highlighting (Shift<Key>f) and repeat the process. This will work even +if the layer that the rat-lines reside on is made invisible - so only the pins and pads +are highlighted. +Be sure to erase the rat-lines (<Key>e erases them all) once you've +duplicated their connectivity by adding your own lines. +When in doubt, the <Key>o will delete only those +rat-lines that are no longer needed. + +

            If connections exist on the board that are not listed in the netlist when +<Key>w is pressed, warning messages are issued and the affected pins and +pads are drawn in a special warnColor until the next Notify() event. +If the entire layout agrees completely with the netlist, a message informs you that +the layout is complete and no rat-lines will be added (since none are needed). +If the layout is complete, but still has rat-lines then you will be warned +that rat-lines remain. If you get no message at all it's probably because some +elements listed in the net list can't be found and where reported in an earlier +message. +There shouldn't be any rat-lines left in a completed layout, only normal lines. + +

            The Shift<Key>w is used to add rat-lines to only those missing connections among +the selected pins and pads. This can be used to add rat-lines in an incremental +manner, or to force a rat-line to route between two points that are not the +closest points within the net. Often it is best to add the rats nest in an incremental fashion, laying +out a sub-section of the board before going further. This is easy to accomplish since +new rat-lines are never added where routed connectivity already makes the necessary +connections. + +

            + +


            +Next: , +Previous: Rats Nest, +Up: Getting Started + +
            + +

            3.13 Design Rule Checking

            + +

            +After you've finished laying out a board, you may want to check +to be certain that none of your interconnections are too closely +spaced or too tenuously touching to be reliably fabricated. The design +rule checking (DRC) function does this for you. Use the command ":DRC()" (without +the quotes of course) to invoke the checker. If there are no problem areas, +you'll get a message to that effect. If any problem is encountered, you will get +a message about it and the affected traces will be highlighted. One part of the +tracks of concern will be selected, while the other parts of concern will have the +"FindConnection" highlighting. The screen will automatically be centered in the +middle of the object having the "FindConnection" (Green) highlighting. The middle of +the object is also the coordinates reported to be "near" the problem. The actual trouble +region will be somewhere on the boundary of this object. If the two parts are +from different nets then there is some place where they approach each +other closer than the minimum rule. If the parts are from the same net, then +there is place where they are only barely connected. Find that place and connect +them better. + +

            After a DRC error is found and corrected you must run the DRC again because +the search for errors is halted as soon as the first problem is found. Unless you've +been extremely careless there should be no more than a few design rule errors +in your layout. The DRC checker does not check for minimum spacing rules to +copper text, so always be very careful when adding copper text to a layout. +The rules for the DRC are specified in the application resource file. The minimum +spacing value (in mils) is given by the Settings.Bloat value. The default +is 7 mils. The minimum touching overlap (in mils) is given by the +Settings.Shrink value. This value defaults to 5 mils. Check with your +fabrication process people to determine the values that are right for you. + +

            If you want to turn off the highlighting produced by the DRC, perform an +undo (assuming no other changes have been made). To restore the highlighting, +use redo. The redo will restore the highlighting quickly without re-running +the DRC checker. + +

            + +


            +Next: , +Previous: Design Rule Checking, +Up: Getting Started + +
            + +

            3.14 Trace Optimizer

            + +

            +PCB includes a flexible trace optimizer. The trace optimizer can be run +after auto routing or hand routing to clean up the traces. + +

            +
            Auto-Optimize
            Performs debumpify, unjaggy, orthopull, vianudge, and viatrim, in that +order, repeating until no further optimizations are performed. + +
            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). + +
            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. + +
            SimpleOpts
            Removing unneeded vias, replacing two or more trace segments in a row +with a single segment. This is usually performed automatically after +other optimizations. + +
            Miter
            Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. + +
            + +
            + +


            +Next: , +Previous: Trace Optimizer, +Up: Getting Started + +
            + +

            3.15 Searching for elements

            + +

            +To locate text or a specific element or grouping of similar elements +choose ‘Select by name’ from the Select menu, then choose the +appropriate subsection. At the bottom of the screen the prompt +pattern: appears. Enter the text or Regular Expressions +of the text to be found. Found text will be highlighted. + +

            + +


            +Next: , +Previous: Searching for elements, +Up: Getting Started + +
            + +

            3.16 Measuring distances

            + +

            +To measure distances, for example the pin-to-pin pitch of a part to +validate a footprint, place the cursor at the starting +measurement point, then press !Ctrl<Key>m. This marks the +current location with a X. The X mark is now the zero point +origin for the relative cursor position display. The cursor display +shows both absolute position and position relative to the mark as +the mouse is moved away from the mark. If a mark is already present, +the mark is removed and the cursor display stops displaying relative +cursor coordinates. + +

            + +


            +Previous: Measuring distances, +Up: Getting Started + +
            + +

            3.17 Vendor Drill Mapping

            + +

            +pcb-rnd includes support for mapping drill holes to a specified set +of sizes used by a particular vendor. Many PCB manufacturers have a +prefered set of drill sizes and charge extra when others are used. +The mapping can be performed on an existing design and can also be +enabled to automatically map drill holes as vias and elements are +instantiated. + +

            The first step in using the vendor drill mapping feature is to create +a resource file describing the capabilities of your vendor. The file +format is the resource file format described in Resource Syntax. +A complete example is given below. + +

                 # Optional name of the vendor
            +     vendor = "Vendor Name"
            +     
            +     # units for dimensions in this file.
            +     # Allowed values:  mil/inch/mm
            +     units = mil
            +     
            +     # drill table
            +     drillmap = {
            +        # When mapping drill sizes, select the nearest size
            +        # or always round up.  Allowed values:  up/nearest
            +        round = up
            +     
            +        # The list of vendor drill sizes.  Units are as specified
            +        # above.
            +        20
            +        28
            +        35
            +        38
            +        42
            +        52
            +        59.5
            +        86
            +       125
            +       152
            +     
            +        # optional section for skipping mapping of certain elements
            +        # based on reference designator, value, or description
            +        # this is useful for critical parts where you may not
            +        # want to change the drill size.  Note that the strings
            +        # are regular expressions.
            +        skips = {
            +           {refdes "^J3$"}  # Skip J3.
            +           {refdes "J3"}  # Skip anything with J3 as part of the refdes.
            +           {refdes "^U[1-3]$" "^X.*"} # Skip U1, U2, U3, and anything starting with X.
            +           {value "^JOHNSTECH_.*"} # Skip all Johnstech footprints based on the value of a part.
            +           {descr "^AMP_MICTOR_767054_1$"} # Skip based on the description.
            +        }
            +     }
            +     
            +     # If specified, this section will change the current DRC
            +     # settings for the design.  Units are as specified above.
            +     drc = {
            +        copper_space = 7
            +        copper_width = 7
            +        silk_width = 10
            +        copper_overlap = 4
            +     }
            +
            +

            The vendor resource is loaded using the LoadVendor action. +This is invoked by entering: +

                 :LoadVendor(vendorfile)
            +
            +

            from within pcb-rnd. Substitute the file name of your vendor +resource file for ‘vendorfile’. This action will load the vendor +resource and modify all the drill holes in the design as well as the +default via hole size for the various routing styles. + +

            Once a vendor drill map has been loaded, new vias and elements will +automatically have their drill hole sizes mapped to the vendor drill +table. Automatic drill mapping may be disabled under the “Settings” +menu. To re-apply an already loaded vendor drill table to a design, +choose “Apply vendor drill mapping” from the “Connects” menu. + +

            See Actions for a complete description of the actions associated +with vendor drill mapping. + +

            Note that the expressions used in the skips section are regular +expressions. See Regular Expressions for an introduction to +regular expressions. + + +

            + +


            +Next: , +Previous: Getting Started, +Up: Top + +
            + +

            4 User Commands

            + +

            The entering of user-commands is initiated by the action routine +Command() (normally bound to the (":") character) which +replaces the bottom statusline with an input area or opens a separate +command window. It is finished by either <Key>Return or +<Key>Escape to confirm or to abort. These two key-bindings +cannot be changed from the resource file. The triggering event, +normally a key press, is ignored. + +

            Commands can be entered in one of two styles, command entry syntax: +“Command arg1 arg2” or action script syntax “Action1(arg1, +arg2); Action2(arg1, arg2);”. Quoting arguments works similar to +bash quoting: + +

              +
            • A backslash (\) is the escape character. It preserves the literal +value of the next character that follows. To get a literal '\' use +"\\". + +
            • Enclosing characters in single quotes preserves the literal value of +each character within the quotes. A single quote may not occur +between single quotes, even when preceded by a blackslash. + +
            • Enclosing characters in double quotes preserves the literal value of +all characters within the quotes, with the exception of '\' which +maintains its special meaning as an escape character. +
            + +

            There are simple usage dialogs for each command and one for the +complete set of commands. + + + + + +

            l [filename]
            Loads a new datafile (layout) and, if confirmed, overwrites any existing unsaved data. +The filename and the searchpath (filePath) are passed to the +command defined by fileCommand. +If no filename is specified a file select box will popup. + +


            le [filename]
            Loads an element description into the paste buffer. +The filename and the searchpath (elementPath) are passed to the +command defined by elementCommand. +If no filename is specified a file select box will popup. + +


            m [filename]
            Loads an layout file into the paste buffer. +The filename and the searchpath (filePath) are passed to the +command defined by fileCommand. +If no filename is specified a file select box will popup. + +


            q[!]
            Quits the program. Uses confirmation dialog if any unsaved data will be lost by quitting. +q! doesn't ask for confirmation, it just quits. + +


            s [filename]
            Data and the filename are passed to the command defined by the resource +saveCommand. It must read the layout data from stdin. +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. + +


            rn [filename]
            Reads in a netlist file. If no filename is given +a file select box will pop up. +The file is read via the command defined by the +RatCommand resource. The command must send its output to stdout. + +

            Netlists are used for generating rat's nests (see Rats Nest) and for +verifying the board layout (which is also accomplished by the Ratsnest +command). + +


            w[q] [filename]
            These commands have been added for the convenience of vi users and +have the same functionality as s combined with q. + +


            actionCommand
            Causes the actionCommand to be executed. This allows you to initiate actions +for which no bindings exist in the resource file. It can be used to initiate any +action with whatever arguments you enter. This makes it possible to do things +that otherwise would be extremely tedious. For example, to change the drilling +hole diameter of all vias in the layout to 32 mils, you could select everything using the +selection menu, then type ":ChangeDrillSize(SelectedVias, 32)". (This will +only work provided the via's diameter is sufficiently large to accommodate a 32 mil hole). +Another example might be to set the grid to 1 mil by typing ":SetValue(Grid, 1)". +Note that some actions use the current cursor location, so be sure to place the cursor +where you want before entering the command. This is one of my favorite new +features in 1.5 and can be a powerful tool. Study the Actions section to +see what actions are available. + +
            + + +
            + + +


            +Next: , +Previous: User Commands, +Up: Top + +
            + +

            5 Command-Line Options

            + +

            +The synopsis of the pcb command is: + +

            pcb [OPTION ...] [LAYOUT-FILE.pcb] to start the application in GUI mode, + +

            or + +

            pcb [-h | -V | --copyright] for a list of options, version, and copyright, + +

            or + +

            pcb -p [OPTION ...] [LAYOUT-FILE.pcb] to print a layout, + +

            or + +

            pcb -x HID [OPTION ...] [LAYOUT-FILE.pcb] to export. + +

            Possible values for the parameter ‘HID’ are: +

            +
            bom
            Export a bill of materials +
            gcode
            Export to G-Code +
            gerber
            Export RS-274X (Gerber) +
            nelma
            Numerical analysis package export +
            png
            export GIF/JPEG/PNG +
            ps
            export postscript +
            eps
            export encapsulated postscript +
            + +

            There are several resources which may be set or reset in addition to the +standard toolkit command-line options. For a complete list refer to +Resources. + + +

            + + + +

            6.1 General Options

            + + +
            +
            --help
            Show help on command line options. +
            + +
            +
            --version
            Show version. +
            + +
            +
            --verbose
            Be verbose on stdout. +
            + +
            +
            --copyright
            Show copyright. +
            + +
            +
            --show-defaults
            Show option defaults. +
            + +
            +
            --show-actions
            Show available actions and exit. +
            + +
            +
            --dump-actions
            Dump actions (for documentation). +
            + +
            +
            --grid-units-mm <string>
            Set default grid units. Can be mm or mil. Defaults to mil. +
            + +
            +
            --backup-interval
            Time between automatic backups in seconds. Set to 0 to disable. +The default value is 60. +
            + +
            +
            --groups <string>
            Layer group string. Defaults to "1,c:2:3:4:5:6,s:7:8". +
            + +
            +
            --route-styles <string>
            A string that defines the route styles. Defaults to
            +"Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000 + :Fat,4000,6000,3500,1000:Skinny,600,2402,1181,600" +
            + +
            +
            --element-path <string>
            A colon separated list of directories or commands (starts with '|'). +The path is passed to the program specified in --element-command. +
            + +
            +
            --action-script <string>
            If set, this file is executed at startup. +
            + +
            +
            --action-string <string>
            If set, this string of actions is executed at startup. +
            + +
            +
            --fab-author <string>
            Name of author to be put in the Gerber files. +
            + +
            +
            --layer-stack <string>
            Initial layer stackup, for setting up an export. A comma separated list of layer +names, layer numbers and layer groups. +
            + +
            +
            --save-last-command
            If set, the last user command is saved. +
            + +
            +
            --save-in-tmp
            If set, all data which would otherwise be lost are saved in a temporary file +/tmp/PCB.%i.save . Sequence ‘%i’ is replaced by the process ID. +
            + +
            +
            --reset-after-element
            If set, all found connections are reset before a new component is scanned. +
            + +
            +
            --ring-bell-finished
            Execute the bell command when all rats are routed. +
            + +
            + +


            +Next: , +Previous: General Options, +Up: Command-Line Options + +
            + +

            6.2 General GUI Options

            + + +
            +
            --pinout-offset-x <num>
            Horizontal offset of the pin number display. Defaults to 100mil. +
            + +
            +
            --pinout-offset-y <num>
            Vertical offset of the pin number display. Defaults to 100mil. +
            + +
            +
            --pinout-text-offset-x <num>
            Horizontal offset of the pin name display. Defaults to 800mil. +
            + +
            +
            --pinout-text-offset-y <num>
            Vertical offset of the pin name display. Defaults to -100mil. +
            + +
            +
            --draw-grid
            If set, draw the grid at start-up. +
            + +
            +
            --clear-line
            If set, new lines clear polygons. +
            + +
            +
            --full-poly
            If set, new polygons are full ones. +
            + +
            +
            --unique-names
            If set, you will not be permitted to change the name of an component to match that +of another component. +
            + +
            +
            --snap-pin
            If set, pin centers and pad end points are treated as additional grid points +that the cursor can snap to. +
            + +
            +
            --all-direction-lines
            Allow all directions, when drawing new lines. +
            + +
            +
            --show-number
            Pinout shows number. +
            + +
            + + +


            +Next: , +Previous: General GUI Options, +Up: Command-Line Options + +
            + +

            6.3 GTK+ GUI Options

            + + +
            +
            --listen
            Listen for actions on stdin. +
            + +
            +
            --bg-image <string>
            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. +
            + +
            +
            --pcb-menu <string>
            Location of the gpcb-menu.res file which defines the menu for the GTK+ GUI. +
            + +
            + +


            +Next: , +Previous: GTK+ GUI Options, +Up: Command-Line Options + +
            + +

            6.4 lesstif GUI Options

            + + +
            +
            --listen
            Listen for actions on stdin. +
            + +
            +
            --bg-image <string>
            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. +
            + +
            +
            --pcb-menu <string>
            Location of the pcb-menu.res file which defines the menu for the lesstif GUI. +
            + +
            + +


            +Next: , +Previous: lesstif GUI Options, +Up: Command-Line Options + +
            + +

            6.5 Colors

            + + +
            +
            --black-color <string>
            Color value for black. Default: ‘#000000’ +
            + +
            +
            --black-color <string>
            Color value for white. Default: ‘#ffffff’ +
            + +
            +
            --background-color <string>
            Background color of the canvas. Default: ‘#e5e5e5’ +
            + +
            +
            --crosshair-color <string>
            Color of the crosshair. Default: ‘#ff0000’ +
            + +
            +
            --cross-color <string>
            Color of the cross. Default: ‘#cdcd00’ +
            + +
            +
            --via-color <string>
            Color of vias. Default: ‘#7f7f7f’ +
            + +
            +
            --via-selected-color <string>
            Color of selected vias. Default: ‘#00ffff’ +
            + +
            +
            --pin-color <string>
            Color of pins. Default: ‘#4d4d4d’ +
            + +
            +
            --pin-selected-color <string>
            Color of selected pins. Default: ‘#00ffff’ +
            + +
            +
            --pin-name-color <string>
            Color of pin names and pin numbers. Default: ‘#ff0000’ +
            + +
            +
            --element-color <string>
            Color of components. Default: ‘#000000’ +
            + +
            +
            --rat-color <string>
            Color of ratlines. Default: ‘#b8860b’ +
            + +
            +
            --invisible-objects-color <string>
            Color of invisible objects. Default: ‘#cccccc’ +
            + +
            +
            --invisible-mark-color <string>
            Color of invisible marks. Default: ‘#cccccc’ +
            + +
            +
            --element-selected-color <string>
            Color of selected components. Default: ‘#00ffff’ +
            + +
            +
            --rat-selected-color <string>
            Color of selected rats. Default: ‘#00ffff’ +
            + +
            +
            --connected-color <string>
            Color to indicate connections. Default: ‘#00ff00’ +
            + +
            +
            --off-limit-color <string>
            Color of off-canvas area. Default: ‘#cccccc’ +
            + +
            +
            --grid-color <string>
            Color of the grid. Default: ‘#ff0000’ +
            + +
            +
            --layer-color-<n> <string>
            Color of layer <n>, where <n> is an integer from 1 to 16. +
            + +
            +
            --layer-selected-color-<n> <string>
            Color of layer <n>, when selected. <n> is an integer from 1 to 16. +
            + +
            +
            --warn-color <string>
            Color of offending objects during DRC. Default value is "#ff8000" +
            + +
            +
            --mask-color <string>
            Color of the mask layer. Default value is "#ff0000" +
            + +
            + +


            +Next: , +Previous: Colors, +Up: Command-Line Options + +
            + +

            6.6 Layer Names

            + + +
            +
            --layer-name-1 <string>
            Name of the 1st Layer. Default is "top". +
            + +
            +
            --layer-name-2 <string>
            Name of the 2nd Layer. Default is "ground". +
            + +
            +
            --layer-name-3 <string>
            Name of the 3nd Layer. Default is "signal2". +
            + +
            +
            --layer-name-4 <string>
            Name of the 4rd Layer. Default is "signal3". +
            + +
            +
            --layer-name-5 <string>
            Name of the 5rd Layer. Default is "power". +
            + +
            +
            --layer-name-6 <string>
            Name of the 6rd Layer. Default is "bottom". +
            + +
            +
            --layer-name-7 <string>
            Name of the 7rd Layer. Default is "outline". +
            + +
            +
            --layer-name-8 <string>
            Name of the 8rd Layer. Default is "spare". +
            + +
            + +


            +Next: , +Previous: Layer Names, +Up: Command-Line Options + +
            + +

            6.7 Paths

            + + +
            +
            --lib-newlib <string>
            Top level directory for the newlib style library. +
            + +
            +
            --lib-name <string>
            The default filename for the library. +
            + +
            +
            --default-font <string>
            The name of the default font. +
            + +
            +
            --file-path <string>
            A colon separated list of directories or commands (starts with '|'). The path +is passed to the program specified in --file-command together with the selected +filename. +
            + +
            +
            --font-path <string>
            A colon separated list of directories to search the default font. Defaults to +the default library path. +
            + +
            +
            --lib-path <string>
            A colon separated list of directories that will be passed to the commands specified +by --element-command and --element-contents-command. +
            + +
            + +


            +Next: , +Previous: Paths, +Up: Command-Line Options + +
            + +

            6.8 Sizes

            + + +

            All parameters should be given with an unit. If no unit is given, 1/100 mil +(cmil) will be used. Write units without space to the +number like 3mm, not 3 mm. +Valid Units are: +

            +
            km
            Kilometer +
            m
            Meter +
            cm
            Centimeter +
            mm
            Millimeter +
            um
            Micrometer +
            nm
            Nanometer +
            in
            Inch (1in = 0.0254m) +
            mil
            Mil (1000mil = 1in) +
            cmil
            Centimil (1/100 mil) +
            + +
            +
            --via-thickness <num>
            Default diameter of vias. Default value is 60mil. +
            + +
            +
            --via-drilling-hole <num>
            Default diameter of holes. Default value is 28mil. +
            + +
            +
            --line-thickness <num>
            Default thickness of new lines. Default value is 10mil. +
            + +
            +
            --rat-thickness <num>
            Thickness of rats. Values from 1 to 19 are fixed width in screen pixels. +Anything larger means PCB units (i.e. 100 means "1 mil"). Default value +is 10mil. +
            + +
            +
            --keepaway <num>
            Default minimum distance between a track and adjacent copper. +Default value is 10mil. +
            + +
            +
            --default-PCB-width <num>
            Default width of the canvas. Default value is 6000mil. +
            + +
            +
            --default-PCB-height <num>
            Default height of the canvas. Default value is 5000mil. +
            + +
            +
            --text-scale <num>
            Default text scale. This value is in percent. Default value is 100. +
            + +
            +
            --alignment-distance <num>
            Specifies the distance between the board outline and alignment targets. +Default value is 2mil. +
            + +
            +
            --grid <num>
            Initial grid size. Default value is 10mil. +
            + +
            +
            --minimum polygon area <num>
            Minimum polygon area. +
            + +
            + +


            +Next: , +Previous: Sizes, +Up: Command-Line Options + +
            + +

            6.9 Commands

            + + +

            pcb uses external commands for input output operations. These commands can be +configured at start-up to meet local requirements. The command string may include +special sequences %f, %p or %a. These are replaced when the +command is called. The sequence %f is replaced by the file name, +%p gets the path and %a indicates a package name. + +

            +
            --font-command <string>
            Command to load a font. +
            + +
            +
            --file-command <string>
            Command to read a file. +
            + +
            +
            --element-command <string>
            Command to read a footprint.
            +Defaults to "M4PATH='%p';export M4PATH;echo 'include(%f)' | m4" +
            + +
            +
            --print-file <string>
            Command to print to a file. +
            + +
            +
            --lib-command-dir <string>
            Path to the command that queries the library. +
            + +
            +
            --lib-command <string>
            Command to query the library.
            +Defaults to "QueryLibrary.sh '%p' '%f' %a" +
            + +
            +
            --lib-contents-command <string>
            Command to query the contents of the library.
            +Defaults to "ListLibraryContents.sh %p %f" or, +on Windows builds, an empty string (to disable this feature). +
            + +
            +
            --save-command <string>
            Command to save to a file. +
            + +
            +
            --rat-command <string>
            Command for reading a netlist. Sequence %f is replaced by the netlist filename. +
            + +
            + +


            +Next: , +Previous: Commands, +Up: Command-Line Options + +
            + +

            6.10 DRC Options

            + + +

            All parameters should be given with an unit. If no unit is given, 1/100 mil +(cmil) will be used for backward compability. Valid units are given in section +Sizes. + +

            +
            --bloat <num>
            Minimum spacing. Default value is 10mil. +
            + +
            +
            --shrink <num>
            Minimum touching overlap. Default value is 10mil. +
            + +
            +
            --min-width <num>
            Minimum width of copper. Default value is 10mil. +
            + +
            +
            --min-silk <num>
            Minimum width of lines in silk. Default value is 10mil. +
            + +
            +
            --min-drill <num>
            Minimum diameter of holes. Default value is 15mil. +
            + +
            +
            --min-ring <num>
            Minimum width of annular ring. Default value is 10mil. +
            + +
            + +


            +Next: , +Previous: DRC Options, +Up: Command-Line Options + +
            + +

            6.11 BOM Creation

            + + +
            +
            --bomfile <string>
            Name of the BOM output file. +
            + +
            +
            --xyfile <string>
            Name of the XY output file. +
            + +
            +
            --xy-unit <unit>
            Unit of XY dimensions. Defaults to mil. +
            + +
            + +


            +Next: , +Previous: BOM Creation, +Up: Command-Line Options + +
            + +

            6.12 Gerber Export

            + + +
            +
            --gerberfile <string>
            Gerber output file prefix. Can include a path. +
            + +
            +
            --all-layers
            Output contains all layers, even empty ones. +
            + +
            +
            --verbose
            Print file names and aperture counts on stdout. +
            + + + +

            6.13 Postscript Export

            + + +
            +
            --psfile <string>
            Name of the postscript output file. Can contain a path. +
            + + + +
            --drill-helper
            Print a centering target in large drill holes. +
            + + + +
            --align-marks
            Print alignment marks on each sheet. This is meant to ease alignment during exposure. +
            + +
            +
            --outline
            Print the contents of the outline layer on each sheet. +
            + +
            +
            --mirror
            Print mirror image. +
            + +
            +
            --fill-page
            Scale output to make the board fit the page. +
            + +
            +
            --auto-mirror
            Print mirror image of appropriate layers. +
            + +
            +
            --ps-color
            Postscript output in color. +
            + + + +
            --ps-bloat <num>
            Amount to add to trace/pad/pin edges. +
            + + + +
            --ps-invert
            Draw objects as white-on-black. +
            + +
            +
            --media <media-name>
            Size of the media, the postscript is fitted to. The parameter +<media-name> can be any of the standard names for paper size: ‘A0’ +to ‘A10’, ‘B0’ to ‘B10’, ‘Letter’, ‘11x17’, +‘Ledger’, ‘Legal’, ‘Executive’, ‘A-Size’, ‘B-size’, +‘C-Size’, ‘D-size’, ‘E-size’, ‘US-Business_Card’, +‘Intl-Business_Card’. +
            + + + +
            --psfade <num>
            Fade amount for assembly drawings (0.0=missing, 1.0=solid). +
            + +
            +
            --scale <num>
            Scale value to compensate for printer sizing errors (1.0 = full scale). +
            + + + +
            --multi-file
            Produce multiple files, one per page, instead of a single multi page file. +
            + +
            +
            --xcalib <num>
            Paper width. Used for x-Axis calibration. +
            + +
            +
            --ycalib <num>
            Paper height. Used for y-Axis calibration. +
            + +
            +
            --drill-copper
            Draw drill holes in pins / vias, instead of leaving solid copper. +
            + + + +
            --show-legend
            Print file name and scale on printout. +
            + +
            + +


            +Next: , +Previous: Postscript Export, +Up: Command-Line Options + +
            + +

            6.14 Encapsulated Postscript Export

            + + +
            +
            --eps-file <string>
            Name of the encapsulated postscript output file. Can contain a path. +
            + +
            +
            --eps-scale <num>
            Scale EPS output by the parameter ‘num’. +
            + + + +
            --as-shown
            Export layers as shown on screen. +
            + +
            +
            --monochrome
            Convert output to monochrome. +
            + + + +
            --only-visible
            Limit the bounds of the EPS file to the visible items. +
            + + + +

            6.15 PNG Options

            + + +
            +
            --outfile <string>
            Name of the file to be exported to. Can contain a path. +
            + +
            +
            --dpi
            Scale factor in pixels/inch. Set to 0 to scale to size specified in the layout. +
            + +
            +
            --x-max
            Width of the png image in pixels. No constraint, when set to 0. +
            + +
            +
            --y-max
            Height of the png output in pixels. No constraint, when set to 0. +
            + +
            +
            --xy-max
            Maximum width and height of the PNG output in pixels. No constraint, when set to 0. +
            + +
            +
            --as-shown
            Export layers as shown on screen. +
            + +
            +
            --monochrome
            Convert output to monochrome. +
            + +
            +
            --only-vivible
            Limit the bounds of the exported PNG image to the visible items. +
            + +
            +
            --use-alpha
            Make the background and any holes transparent. +
            + +
            +
            --format <string>
            File format to be exported. Parameter <string> can be ‘PNG’, +‘GIF’, or ‘JPEG’. +
            + +
            +
            --png-bloat <num><dim>
            Amount of extra thickness to add to traces, pads, or pin edges. The parameter +‘<num><dim>’ is a number, appended by a dimension ‘mm’, ‘mil’, or +‘pix’. If no dimension is given, the default dimension is 1/100 mil. +
            + + + +
            --photo-mode
            Export a photo realistic image of the layout. +
            + +
            +
            --photo-flip-x
            In photo-realistic mode, export the reverse side of the layout. Left-right flip. +
            + +
            +
            --photo-flip-y
            In photo-realistic mode, export the reverse side of the layout. Up-down flip. +
            + +
            + +


            +Next: , +Previous: PNG Options, +Up: Command-Line Options + +
            + +

            6.16 lpr Printing Options

            + + +
            +
            --lprcommand <string>
            Command to use for printing. Defaults to lpr. This can be used to produce +PDF output with a virtual PDF printer. Example:
            +--lprcommand "lp -d CUPS-PDF-Printer". +
            +In addition, all Postscript Export options are valid. + +
            + +


            +Previous: lpr Printing Options, +Up: Command-Line Options + +
            + +

            6.17 nelma Options

            + + +
            +
            -- basename <string>
            File name prefix. +
            + +
            +
            --dpi <num>
            Horizontal scale factor (grid points/inch). +
            + +
            +
            --copper-height <num>
            Copper layer height (um). +
            + +
            +
            --substrate-height <num>
            Substrate layer height (um). +
            + +
            +
            --substrate-epsilon <num>
            Substrate relative epsilon. +
            + + +
            + +


            +Next: , +Previous: Command-Line Options, +Up: Top + +
            + +

            6 X11 Interface

            + +

            +This chapter gives an overview about the additional X11 resources which +are defined by pcb-rnd as well as the defined action routines. + +

            + +
            + +


            +Next: , +Up: X11 Interface + +
            + +

            7.1 Non-Standard X11 Application Resources

            + +

            +In addition to the toolkit resources, pcb-rnd defines the +following resources: + + + + +

            absoluteGrid (boolean)
            Selects if either the grid is relative to the position where it has changed +last or absolute, the default, to the origin (0,0). + +


            alignmentDistance (dimension)
            Specifies the distance between the boards outline to the alignment targets. + +


            allDirectionLines (boolean)
            Enables (default) or disables clipping of new lines to 45 degree angles. + +


            backgroundImage (string)
            If specified, this image will be drawn as the background for the +board. The purpose of this option is to allow you to use a scan of an +existing layout as a prototype for your new layout. To do this, there +are some limitations as to what this image must be. The image must be +a PPM binary image (magic number ‘P6’). It must have a maximum +pixel value of 255 or less (i.e. no 16-bit images). It must represent +the entire board, as it will be scaled to fit the board dimensions +exactly. Note that it may be scaled unevenly if the image doesn't +have the same aspect ratio of your board. You must ensure that the +image does not use more colors than are available on your system +(mostly this is for pseudo-color displays, like old 8-bit displays). +For best results, I suggest the following procedure using The Gimp: +Load your image (any type). Image->Scale if needed. +Image->Colors->Curves and for each of Red, Green, and Blue channel +move the lower left point up to about the 3/4 line (value 192). This +will make your image pale so it doesn't interfere with the traces +you'll be adding. Image->Mode->Indexed and select, say, 32 colors +with Normal F-S dithering. File->Save As, file type by extension, +use .ppm as the extension. Select Raw formatting. + +


            backupInterval (int)
            pcb-rnd has an automatic backup feature which saves the current data +every n seconds. The default is 300 seconds. A value of zero disables +the feature. The backup file is named /tmp/PCB.%i.backup by +default (this may have been changed at compilation time via the +BACKUP_NAME +variable in globalconfig.h). +%i is replaced by the process ID. +See also, the command-line option –backup-interval. + +


            Bloat (dimension)
            Specifies the minimum spacing design rule in mils. + +


            connectedColor (color)
            All pins, vias, lines and rectangles which are selected during a connection +search are drawn with this color. The default value is determined by +XtDefaultForeground. + +


            cross hairColor (color)
            This color is used to draw the cross hair cursor. The color is a result of +a XOR operation with the contents of the Layout area. The result +also depends on the default colormap of the X11 server because only +the colormap index is used in the boolean operation and pcb-rnd doesn't +create its own colormap. The default setting is XtDefaultForeground. + +


            elementColor (color)
            elementSelectedColor (color)
            The elements package part is drawn in these colors, for normal and selected +mode, respectively, which both default to XtDefaultForeground. + +


            elementCommand (string)
            pcb-rnd uses a user defined command to read element files. This resources +is used to set the command which is executed by the users default shell. +Two escape sequences are defined to pass the selected filename (%f) and the +current search path (%p). The command must write the element data +to its standard output. The default value is +
                          M4PATH="%p";export M4PATH;echo 'include(%f)' | m4
            +
            +

            Using the GNU version of m4 is highly recommended. +See also, the command-line option –element-command. + +


            elementPath (string)
            A colon separated list of directories or commands (starts with '|'). +The path is passed to the program specified in elementCommand together +with the selected element name. A specified command will be executed in order +to create entries for the fileselect box. It must write its results to +stdout one entry per line. +See also, the user-command le[!]. + +


            fileCommand (string)
            The command is executed by the user's default shell whenever existing layout +files are loaded. Data is read from the command's standard output. +Two escape sequences may be specified to pass the selected filename (%f) +and the current search path (%p). The default value is: +
                          cat %f
            +
            +

            See also, the command-line option –file-command. + +


            filePath (string)
            A colon separated list of directories or commands (starts with '|'). +The path is passed to the program specified in fileCommand together +with the selected filename. A specified command will be executed in order +to create entries for the fileselect box. It must write its results to +stdout one entry per line. +See also, the user-command l[!]. + +


            fontCommand (string)
            Loading new symbol sets also is handled by an external command. You again +may pass the selected filename and the current search path by passing +%f and %p in the command string. Data is read from the commands standard +output. This command defaults to +
                          cat %f
            +
            +

            See also, the command-line option –font-command. + +


            fontFile (string)
            The default font for new layouts is read from this file which is searched +in the directories as defined by the resource fontPath. +Searching is only performed if the filename does not contain a directory +component. +The default filename is default_font. + +


            fontPath (string)
            This resource, a colon separated list of directories, defines the searchpath +for font files. See also, the resource fontFile. + +


            grid (int)
            This resources defines the initial value of one cursor step. It defaults +to 100 mil and any changes are saved together with the layout data. + +


            gridColor (color)
            This color is used to draw the grid. The color is a result of +a INVERT operation with the contents of the Layout area. The result +also depends on the default colormap of the X11 server because only +the colormap index is used in the boolean operation and pcb-rnd doesn't +create its own colormap. The default setting is XtDefaultForeground. + +


            invisibleObjectsColor (color)
            Elements located on the opposite side of the board are drawn in this color. +The default is XtDefaultForeground. + +


            layerColor1..MAX_LAYER (color)
            layerSelectedColor1..MAX_LAYER (color)
            These resources define the drawing colors of the different layers in +normal and selected state. All values are preset to XtDefaultForeground. + +


            layerGroups (string)
            The argument to this resource is a colon separated list of comma separated +layer numbers (1..MAX_LAYER). All layers within one group are switched on/off +together. The default setting is 1:2:3:...:MAX_LAYER which means +all layers are handled separately. Grouping layers one to three looks like +1,2,3:4:...:MAX_LAYER + +


            layerName1..MAX_LAYER (string)
            The default name of the layers in a new layout are determined by these +resources. The defaults are empty strings. + +


            libraryCommand (string)
            pcb-rnd uses a command to read element data from libraries. +The resources is used to set the command which is executed by the users +default shell. Three escape sequences are defined to pass the selected +filename (%f), the current search path (%p) as well (%a) as the three +parameters template, value and package to the command. +It must write the element data to its standard output. The default value is +
                          NONE/share/pcb/oldlib/QueryLibrary.sh %p %f %a
            +
            +


            libraryContentsCommand (string)
            Similar to libraryCommand, pcb-rnd uses the command specified +by this resource to list the contents of a library. +
                      	NONE/share/pcb/oldlib/ListLibraryContents.sh %p %f
            +
            +

            is the default. + +


            libraryFilename (string)
            The resource specifies the name of the library. The default value is +pcblib unless changed at compile time +with the LIBRARYFILENAME variable in globalconfig.h. + +


            libraryPath (string)
            A colon separated list of directories that will be passed to the commands +specified by elementCommand and elementContentsCommand. + +


            lineThickness (dimension)
            The value, in the range [1..250] (the range may be changed at compile +time with the MIN_LINESIZE and MAX_LINESIZE variables in +globalconfig.h), defines the +initial thickness of new lines. The value is preset to ten mil. + +


            media (<predefined> | <width>x<height>+-<left_margin>+-<top_margin>)
            The default (user defined) media of the PostScript device. Predefined +values are a3, a4, a5, letter, tabloit, +ledger, legal, and executive. +The second way is to specify the medias width, height and margins in mil. +The resource defaults to a4 size unless changed at compile time +with the DEFAULT_MEDIASIZE variable in globalconfig.h. + +


            offLimitColor (color)
            The area outside the current maximum settings for width and height is drawn +with this color. The default value is determined by XtDefaultBackground. + +


            pinColor (color)
            pinSelectedColor(color)
            This resource defines the drawing color of pins and pads in both states. +The values are preset to XtDefaultForeground. + +


            pinoutFont (string)
            This fonts are used to display pin names. There is one font for each zoom +value. The values are preset to XtdefaultFont. + +


            pinoutNameLength (int)
            This resource limits the number of characters which are displayed for +pin names in the pinout window. By default the string length is limited +to eight characters per name. + +


            pinoutOffsetX (int)
            pinoutOffsetY (int)
            These resources determine the offset in mil of the circuit from the +upper left corner of the window when displaying pinout information. +Both default to 100 mil. + +


            pinoutTextOffsetX (int)
            pinoutTextOffsetY (int)
            The resources determine the distance in mil between the drilling hole of a pin +to the location where its name is displayed in the pinout window. +They default to X:50 and Y:0. + +


            pinoutZoom (int)
            Sets the zoom factor for the pinout window according to the formula: +scale = 1:(2 power value). Its default value is two which results in +a 1:4 scale. + +


            printCommand (string)
            Default file for printouts. If the name starts with a '|' the output +is piped through the command. A %f is replaced by the current filename. +There is no default file or command. + +


            raiseLogWindow (boolean)
            The log window will be raised when new messages arrive if this resource +is set true, the default. + +


            ratCommand (string)
            Default command for reading a netlist. A %f is replaced by the netlist +filename. Its default value is "cat %f". + +


            ratPath (string)
            Default path to look for netlist files. It's default value is "." + +


            resetAfterElement (boolean)
            If set to true, all found connections will be reset before a new +element is scanned. This will produce long lists when scanning the whole +layout for connections. The resource is set to false by default. +The feature is only used while looking up connections of all elements. + +


            ringBellWhenFinished (boolean)
            Whether to ring the bell (the default) when a possibly lengthy operation +has finished or not. +See also, the command-line option –ring-bell-finished. + +


            routeStyle (string)
            Default values for the menu of routing styles (seen in the sizes menu). +The string is a comma separated list of name, line thickness, +via diameter, and via drill size. +e.g. "Fat,50,100,40:Skinny,8,35,20:75Ohm,110,110,20" +See also, the command-line option –route-styles and Sizes Menu + +


            rubberBandMode (boolean)
            Whether rubberband move and rotate (attached lines stretch like +rubberbands) is enabled (the default). + +


            saveCommand (string)
            This command is used to save data to a layout file. The filename may be +indicated by placing %f in the string. It must read the data from +its standard input. The default command is: +
                          cat - > %f
            +
            +

            See also, the command-line option –save-command. + +


            saveInTMP (boolean)
            Enabling this resource will save all data which would otherwise be lost +in a temporary file /tmp/PCB.%i.save. The file name may +be changed at compile time +with the EMERGENCY_NAME variable in globalconfig.h. +. +%i is replaced by the process ID. +As an example, loading a new layout when the old one hasn't been saved would +use this resource. +See also, the command-line option –save-in-tmp. + +


            saveLastCommand (boolean)
            Enables the saving of the last entered user command. The option is +disabled by default. +See also, the command-line option –save-last-command. + +


            Shrink (dimension)
            Specifies the minimum overlap (touching) design rule in mils. + +


            size (<width>x<height>)
            Defines the width and height of a new layout. The default is +7000x5000 unless changed at compile time +with the DEFAULT_SIZE variable in globalconfig.h. + +


            stipllePolygons (boolean)
            Determines whether to display polygons on the screen with a stippled +pattern. Stippling can create some amount of transparency so that +you can still (to some extent) see layers beneath polygons. +It defaults to False. + +


            textScale (dimension)
            The font scaling in percent is defined by this resource. The default is +100 percent. + +


            useLogWindow (boolean)
            Several subroutines send messages to the user if an error occurs. +This resource determines if they appear inside the log window or as a separate +dialog box. See also, the resource raiseLogWindow and the command line +option -loggeometry. +The default value is true. + +


            viaColor (color)
            viaSelectedColor (color)
            This resource defines the drawing color of vias in both states. +The values are preset to XtDefaultForeground. + +


            viaThickness (dimension)
            viaDrillingHole (dimension)
            The initial thickness and drilling hole of new vias. The values must be in the +range [30..400] (the range may be changed at compile +time with the MIN_PINORVIASIZE and MAX_PINEORVIASIZE variables in +globalconfig.h), with at least 20 +mil of copper. +The default thickness is 40 mil and the default drilling hole is +20 mil. + +


            volume (int)
            The value is passed to XBell() which sets the volume of the X +speaker. +The value lies in the range -100..100 and it defaults to the maximum volume of +100. + +


            warnColor (color)
            This resources defines the color to be used for drawing pins and pads when +a warning has been issued about them. + +


            zoom (int)
            The initial value for output scaling is set according to the following +formula: scale = 1:(2 power value). It defaults to three which results +in an output scale of 1:8. + +
            + +

            Refer also to Command-Line Options. + +

            + +


            +Next: , +Previous: Resources, +Up: X11 Interface + +
            + +

            7.2 Actions

            + +

            +All user accessible commands may be bound to almost any X event. Almost +no default binding for commands is done in the binaries, so it is vital for the +application that at least a system-wide application resource file exists. +This file normally resides in the share/pcb directory and +is called pcb-rnd. The bindings to which the manual refers to are the +ones as defined by the shipped resource file. Besides binding an action to +an X11 event, you can also execute any action command using a ":" command +(see User Commands). + +

            Take special care about translations related to the functions keys and the +pointer buttons because most of the window managers use them too. +Change the file according to your hardware/software environment. +You may have to replace all occurances of baseTranslations to +translations if you use a X11R4 server. + +

            Passing Object as an argument to an action routine causes the object +at the cursor location to be changed, removed or whatever. If more than +one object is located at the cross hair position the smallest type is used. +If there are two of the same type the newer one is taken. +SelectedObjects will handle all selected and visible objects. + + + + + + +

            AddRats(AllRats|SelectedRats)
            Adds rat-lines to the layout using the loaded netlist file (see the :rn, +User Commands.). Rat lines are added on the active layer using the current +line thickness shown in the status line. +Only missing connectivity is added by the +AddRats command so if, for example, the layout is complete nothing will be added. +Rat lines may be drawn different to other lines on the screen +to make them easier to identify since they cannot appear in a completed layout. +The rat-lines are added in the minimum length straight-line tree pattern +(always ending on pins or pads) that satisfies the missing connectivity in the circuit. +If a SMD pad is unreachable on the active layer, a warning will be issued +about it and the rat-line to that pad will not be generated. +If connections exist on the board which are not listed in the netlist while +AllRats are being added, warning messages will be issued and the affected pins and +pads will be drawn in a special warnColor until the next Notify() event. +If the entire layout agrees completely with the net-list a message informs you that +the layout is complete and no rat-lines are added (since none are needed). +If SelectedRats +is passed as the argument, only those missing connections that might connect among +the selected pins and pads are drawn. +Default: +
                      None<Key>w:	AddRats(AllRats)
            +          !Shift<Key>w:	AddRats(SelectedRats)
            +          None<Key>o:	DeleteRats(AllRats) AddRats(AllRats)
            +          !Shift<Key>o:	DeleteRats(SelectedRats) AddRats(SelectedRats)
            +
            +


            ApplyVendor()
            Applies an already loaded vendor drill map to the design. +
                      ApplyVendor()
            +
            +


            Atomic(Save|Restore|Block|Close)
            Controls the undo grouping of sequences of actions. Before the first action +in a group, Atomic(Save) should be issued. After each action that might +be undoable, Atomic(Restore) should be issued. Atomic(Block) concludes +and save the undo grouping if there was anything in the group to undo. +Atomic(Close) concludes and save the undo grouping even if nothing was +actually done. Thus it might produce an "empty" undo. This can be useful +when you want to use undo in a group of actions. + +


            Bell([-100..100])
            Rings the bell of your display. If no value is passed the setting +of the resource volume will be used. + +


            ChangeClearSize(Object, value[, unit])
            ChangeClearSize(SelectedPins|SelectedVias, value[, unit])
            The effect of this action depends on if the soldermask display is presently +turned on or off. If soldermask is displayed, then the soldermask +relief size will be changed. If soldermask display is turned off, +then the clearance to polygons will be changed. +unit is "mil" or "mm". If not specified the units will default +to the internal unit of 0.01 mil. +
                      !Mod1<Key>k:      ChangeClearSize(Object, +2, mil)
            +          !Mod1 Shift<Key>k: ChangeClearSize(Object, -2, mil)
            +
            +


            ChangeDrillSize(Object, value[, unit])
            ChangeDrillSize(SelectedPins|SelectedVias, value[, unit])
            This action routine changes the drilling hole of pins and vias. +If value starts with + or -, then it adds (or subtracts) +value from the current hole diameter, otherwise it sets the +diameter to the value. +unit is "mil" or "mm". If not specified the units will default +to the internal unit of 0.01 mil. +Default: +
                      !Mod1<Key>s:       Change2ndSize(Object, +5, mil)
            +          !Mod1 Shift<Key>s: Change2ndSize(Object, -5, mil)
            +
            +

            ChangeFlag(Object|SelectElements|SelectedPins|SelectedVias|Selected,thermal|octagon|square,0|1)
            Sets/clears the indicated flag. This adds/removes thermals, adds/removes the flag +which indicates a pin/pad should be square, or adds/removes the flag which +indicates a pin/pad should be octagonal. +
                      :ChangeFlag(SelectedVias,thermal,1)
            +          :ChangeFlag(SelectedPads,square,0)
            +
            +


            ChangeHole(Object|SelectedVias)
            This action routine converts a via to and from a hole. A hole is +a via that has no copper annulus. The drill size for the via +determines the hole diameter. +
                      !Ctrl<Key>h:	ChangeHole(Object)
            +
            +


            ChangeName(Object)
            ChangeName(Layer|Layout)
            Changes the name of the visible object at the cursor location. A text object +doesn't have a name therefore the text string itself is changed. +The element name currently used for display is always the one changed with this +command. +See Display(Description|NameOnPCB|Value) for details. +Passing Layer changes the current layers name. +Default: +
                      None<Key>n: ChangeName(Object)
            +
            +

            ChangeOctagon(Object|SelectElements|SelectedPins|SelectedVias|Selected)
            Toggles what shape the affected pin(s) or via(s) will be drawn when they +are not square. The shape will either be round or octagonal. +Default: +
                      !Ctrl<Key>o: ChangeOctagon(Object)
            +
            +


            ChangePinName(ElementName, PinNumber, PinName)
            Changes the name for a specified pin or pad number on a specified element. +This action is typically used to forward annotate pin/pad names from a schematic +to the layout. +
                      ChangePinName(U1, 14, VDD)
            +
            +


            ChangeSize(Object, value[, unit])
            ChangeSize(SelectedLines|SelectedPins|SelectedVias, value[, unit])
            ChangeSize(SelectedPads|SelectedTexts|SelectedNames, value[, unit])
            ChangeSize(SelectedElements, value[, unit])
            To change the size of an object you have to bind these action to some +X event (or use :ChangeSize(...)). If value begins with +a + or - then the value will be added (or subtracted) from the current +size, otherwise the size is set equal to value. Range checking is +done to insure that none of the maximum/minimums of any size are violated. +If Object is passed then a single object at the cursor location is +changed. If any of the Selected arguments are passed then all selected +and visible objects of that type are changed. If the type being modified is +an element, then the thickness of the silkscreen lines defining the element +is changed. +unit is "mil" or "mm". If not specified the units will default +to the internal unit of 0.01 mil. +Default: +
                      None<Key>s:   ChangeSize(Object, +5)
            +          !Shift<Key>s: ChangeSize(Object, -5)
            +
            +


            ChangeSquare(Object|SelectedElements|SelectedPins)
            Toggles the setting of the square flag. The flag is used to identify a +certain pin, normally the first one, of circuits. It is also used to +make SMD pads have square ends. +
                      None<Key>q:   ChangeSquare(Object)
            +
            +

            ClrFlag(Object|SelectElements|SelectedPins|SelectedVias|Selected,thermal|octagon|square)
            Clears the indicated flag. This removes thermals, removes the flag +which indicates a pin/pad should be square, or removes the flag which +indicates a pin/pad should be octagonal. +
                      :ClrFlag(SelectedVias,thermal)
            +
            +


            Command()
            Calling Command() pops up an input line at the bottom of the window +which allows you to enter commands. Including all action commands! +The dialog ends when None<Key>Return +to confirm or None<Key>Escape to abort is entered. +Default: +
                      <Key>colon: Command()
            +
            +


            Connection(Find)
            Connection(ResetFoundLinesAndRectangles|ResetPinsViasAndPads|Reset)
            The Connection() action is used to mark all connections from one pin, +line or via to others. +The ResetFoundLinesAndRectangles, ResetFoundPinsAndVias and +Reset arguments may be used to reset all marked lines and rectangles, +vias and pins or all of them. The search starts with the pin or via +at the cursor position. All found objects are drawn with the color +defined by the resource connectedColor. +See also, Display(Description|NameOnPCB|Value). +Default: +
                      !Shift<Key>c: Connection(Reset)
            +          None<Key>f:   Connection(Find)
            +          !Shift<Key>f: Connection(Reset)
            +
            +


            DeleteRats(AllRats|SelectedRats)
            This routine deletes either all rat-lines in the layout, or only +the selected and visible ones. Non-rat-lines and other layout +objects are unaffected. +Default: +
                      None<Key>e:   DeleteRats(AllRats)
            +          !Shift<Key>e: DeleteRats(SelectedRats)
            +
            +


            DisableVendor()
            Disables automatic drill size mapping to the loaded vendor drill table. +
                      DisableVendor()
            +
            +


            DisperseElements(All|Selected)
            Disperses either all elements or only the selected elements in the +layout. This action should be used at the +start of a design to spread out all footprints before any placement or +routing is done. +
                      DisperseElements(All)
            +
            +


            Display(Description|NameOnPCB|Value)
            Display(Toggle45Degree|CycleClip)
            Display(Grid|ToggleGrid)
            Display(ToggleRubberBandMode)
            Display(Center|ClearAndRedraw|Redraw)
            Display(Pinout|PinOrPadName)
            This action routines handles some output related settings. It is +used to center the display around the cursor location and to redraw the +output area optionally after clearing the window. +Centering is done with respect to the grid setting. Displaying the +grid itself may be switched on and off by Grid but only if +the distance between two pixels exceeds 4 pixels. +pcb-rnd is able to handle several labels of an element. One of them +is a description of the functionality (eg resistor), the second should be +a unique identifier (R1) whereas the last one is a value (100k). +The Display() action selects which of the names is displayed. +It also controls which name will be affected by the ChangeName command. +If ToggleGrid is passed, pcb-rnd changes between relative +('rel' in the statusline) and absolute grid (an 'abs' in the statusline). +Relative grid means the pointer position when the command is issued is +used as the grid origin; while (0,0) is used in the absolute grid case. +Passing Pinout displays the pinout of the element at the current +cursor location whereas PinOrPadName toggles displaying of the +pins or pads name under the cursor. If none of them matches but the cursor +is inside of an element, the flags is toggled for all of its pins and pads. +For details about rubberbands see also the details about Mode. +Default: +
                      None<Key>c:  Display(Center)
            +          None<Key>d:  Display(PinOrPadName)
            +          !Shift<Key>d: Display(Pinout)
            +          None<Key>r:  Display(ClearAndRedraw)
            +          None<Key>.:  Display(Toggle45Degree)
            +          None<Key>/:  Display(CycleClip)
            +
            +


            DRC()
            Initiates design rule checking of the entire layout. Must be repeated +until no errors are found. + +

            ExecuteFile(filename)
            Executes the PCB actions contained in the specified file. +This can be used to automate a complex sequence of operations. +
                      :ExecuteFile(custom.cmd)
            +
            +

            The command file contains a list of PCB actions. Blank lines +are ignored and lines starting with a # are treated as comment +lines. For example +

                      # This is a comment line
            +          Display(Grid)
            +          SetValue(Zoom,2)
            +          DRC()
            +
            +


            EditLayerGroups()
            Pops up a dialog box to edit the layergroup setting. The function is also +available from the Objects menu. +There are no defaults. + +


            EnableVendor()
            Enables automatic drill size mapping to the loaded vendor drill table. +
                      EnableVendor()
            +
            +


            Load(ElementToBuffer|Layout|LayoutToBuffer|Nelist)
            This routine pops up a fileselect box to load layout, element data, +or netlist. +The passed filename for layout data is saved and may be reused. +ElementToBuffer and LayoutToBuffer load the data into the +current buffer. +There are no defaults. + +


            LoadVendor(vendorfile)
            Loads the specified vendor resource file. +
                      LoadVendor(myvendor.res)
            +
            +


            MarkCrosshair()
            This routine marks the current cursor location with an X, and then +the cursor display shows both absolute position and position relative to +the mark. If a mark is already present, this routine removes it and +stops displaying relative cursor coordinates. +Defaults: +
                      !Ctrl<key>m:	MarkCrosshair()
            +
            +


            Mode(Copy|InsertPoint|Line|Move|None|PasteBuffer|Polygon|Thermal)
            Mode(Remove|Rectangle|RubberbandMove|Text|Via)
            Mode(Cycle)
            Mode(Notify)
            Mode(Save|Restore)
            Switches to a new mode of operation. The active mode is displayed by a thick +line around the matching mode selector button. +Most of the functionality of pcb-rnd is implemented by selecting a mode +and calling Mode(Notify). The arguments Line, Polygon, +Rectangle, Text and Via are used to create the +appropriate object whenever Mode(Notify) is called. Some of them, +such as Polygon, need more than one call for one object to be created. +InsertPoint adds points to existing polygons or lines. +Save and Restore are used to temporarily save the mode, switch +to another one, call Mode(Notify) and restore the saved one. Have +a look at the application resource file for examples. +Copy and Move modes are used to change an object's location and, +optionally, to create a new one. The first call of Mode(Notify) attaches +the object at the pointer location to the cross hair whereas the second +one drops it to the layout. The rubberband version of move performs the +move while overriding the current rubberband mode. +Passing PasteBuffer attaches the contents of the currently selected +buffer to the cross hair. Each call to Mode(Notify) pastes this contents +to the layout. Mode(Cycle) cycles through the modes available in the +mode-button pallet. +Mode(None) switches all modes off. +Default: +
                      <Key>Escape:             Mode(None)
            +          <Key>space:              Mode(Cycle)
            +          None<Key>BackSpace:      Mode(Save) Mode(Remove) Mode(Notify) Mode(Restore)
            +          None<Key>Delete:         Mode(Save) Mode(Remove) Mode(Notify) Mode(Restore)
            +          None<Key>F1:             Mode(Via)
            +          None<Key>F2:             Mode(Line)
            +          None<Key>F3:             Mode(PasteBuffer)
            +          None<Key>F4:             Mode(Rectangle)
            +          None<Key>F5:             Mode(Text)
            +          None<Key>F6:             Mode(Polygon)
            +          None<Key>F7:             Mode(Thermal)
            +          None<Key>F8:		 Mode(Arc)
            +          None<Key>Insert:         Mode(InsertPoint)
            +          None<Key>[:              Mode(Save) Mode(Move) Mode(Notify)
            +          None<Key>]:              Mode(Notify) Mode(Restore)
            +          None<Btn1>:          Mode(Notify)
            +          !Shift Ctrl<Btn1>:   Mode(Save) Mode(Remove) Mode(Notify) Mode(Restore)
            +          None<Btn2Down>:          Mode(Save) Mode(Move) Mode(Notify)
            +          None<Btn2Up>:            Mode(Notify) Mode(Restore)
            +          !Mod1<Btn2Down>:       Mode(Save) Mode(Copy) Mode(Notify)
            +          !Mod1<Btn2Up>:         Mode(Notify) Mode(Restore)
            +          Shift BTNMOD<Btn2Down>: Mode(Save) Mode(RubberbandMove) Mode(Notify)
            +
            +


            MovePointer(delta_x, delta_y)
            With this function it is possible to move the cross hair cursor by using the +cursor keys. The X server's pointer follows because the necessary +events are generated by pcb-rnd. All movements are performed with respect +to the currently set grid value. +Default: +
                      None<Key>Up:      MovePointer(0, -1)
            +          !Shift<Key>Up:    MovePointer(0, -10)
            +          None<Key>Down:    MovePointer(0, 1)
            +          !Shift<Key>Down:  MovePointer(0, 10)
            +          None<Key>Right:   MovePointer(1, 0)
            +          !Shift<Key>Right: MovePointer(10, 0)
            +          None<Key>Left:    MovePointer(-1, 0)
            +          !Shift<Key>Left:  MovePointer(-10, 0)
            +
            +


            MoveToCurrentLayer(Object|SelectedObjects)
            The function moves a single object at the cross hair location or all selected +objects to the current layer. Elements are not movable by this function. +They have to be deleted and replaced on the other side. +If a line segment is moved and the movement would result in a loss of +connectivity to another segment then via(s) are automatically added to +maintain the connectivity. +
                      None<Key>m:       MoveToCurrentLayer(Object)
            +          !Shift<Key>m:     MoveToCurrentLayer(SelectedObjects)
            +
            +


            New()
            Clear the current layout and starts a new one after entering its name. +Refer to the resource backup for more information. +No defaults. + +


            PasteBuffer(AddSelected|Clear|1..5)
            PasteBuffer(Rotate, 1..3)
            PasteBuffer(Convert)
            This action routine controls and selects the pastebuffer as well as all +cut-and-paste operations. Passing a buffer number selects one in of the +range 1..5. The statusline is updated with the new number. +Rotate performs a number of 90 degree counter clockwise rotations +of the buffer contents. AddSelected as first argument copies all +selected and visible objects into the buffer. Passing Clear removes +all objects from the currently selected buffer. Convert causes +the contents of the buffer (lines, arc, vias) to be converted into an +element definition. Refer to Pastebuffer +for examples. +Default: +
                      !Ctrl<Key>x:       PasteBuffer(Clear) PasteBuffer(AddSelected)
            +          		   Mode(PasteBuffer)
            +          !Shift Ctrl<Key>x: PasteBuffer(Clear) PasteBuffer(AddSelected)
            +          		   RemoveSelected() Mode(PasteBuffer)
            +          !Mod1<Key>c:       PasteBuffer(Clear) PasteBuffer(AddSelected)
            +          !Mod1<key>x:       PasteBuffer(Clear) PasteBuffer(AddSelected)
            +          		   RemoveSelected()
            +          !Shift<Key>1:      PasteBuffer(1)
            +          !Shift<Key>2:      PasteBuffer(2)
            +          !Shift<Key>3:      PasteBuffer(3)
            +          !Shift<Key>4:      PasteBuffer(4)
            +          !Shift<Key>5:      PasteBuffer(5)
            +          None<Key>F3:       Mode(PasteBuffer)
            +
            +


            Polygon((Close|PreviousPoint)
            Polygons need a special action routine to make life easier. Calling +Polygon(PreviousPoint) resets the newly entered corner to the +previous one. The Undo action will call Polygon(PreviousPoint) +when appropriate to do so. 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. +Default: +
                      None<Key>p:             Polygon(Close)
            +          !Shift<Key>p:           Polygon(Close)
            +
            +


            Print()
            Pops up a print control box that lets you select the output +device, scaling and many more options. Each run creates all +files that are supported by the selected device. These are +mask files as well as drilling files, silk screens and so on. The table +shows the filenames for all possible files: +
                      	POSIX (extension)             8.3 filename
            +          		---------------------------------------------
            +          		*_componentmask.*             cmsk.*
            +          		*_componentsilk.*             cslk.*
            +          		*_soldermask.*                smsk.*
            +          		*_soldersilk.*                sslk.*
            +          		*_drill.*                     dril.*
            +          		*_groundplane.*               gpl.*
            +          		*_group[1..8].*     [..8].*
            +
            +

            The output may be sent to a post-processor by starting the filename with the +pipe ("|") character. Any "%f" in a command is replaced +with the current filename. The function is available from the file menu. +There are no defaults. + +


            Quit()
            Quits the application after confirming the operation. +Default: +
                      <Message>WM_PROTOCOLS: Quit()
            +
            +


            Redo()
            This routine 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. +Default: +
                      !Shift<Key>r:	Redo()
            +
            +


            RemoveSelected()
            This routine removes all visible and selected objects. +There are no defaults. + +


            Report(Object|DrillReport)
            This routine pops up a dialog box describing the various +characteristics of an object (or piece of an object such as a pad or pin) +in the layout at the cursor position, or a report about all of the +drill holes in the layout. +There are no defaults. + +


            RouteStyle(1|2|3|4)
            This routine copies the sizes corresponding to the numbered route style +into the active line thickens, via diameter, and via drill size. +Defaults: +
                      !Ctrl<Key>1: RouteStyle(1)
            +          ...
            +          !Ctrl<Key>NUM_STYLES: RouteStyle(NUM_STYLES)
            +
            +

            The variable NUM_STYLES is set at compile time in +globalconfig.h. + +


            Save(Layout|LayoutAs)
            Save(AllConnections|AllUnusedPins|ElementConnections)
            Passing Layout saves the layout using the file from which it was +loaded or, if it is a new layout, calls Save(LayoutAs) which queries +the user for a filename. +The values: AllConnections, AllUnusedPins and +ElementConnections start a connection scan and save all connections, +all unused pins or the connections of a single element to a file. +There are no defaults. + +


            Select(All|Block|Connection|ToggleObject)
            Select(ElementByName|ObjectByName|PadByName|PinByName)
            Select(TextByName|ViaByName)
            Toggles either the selection flag of the object at the cross hair position +(ToggleObject) or selects all visible objects, all inside a +rectangle or all objects which have been found during the last connection +scan. The ByName functions use a Regular Expressions search, +always case insensitive, to select the objects. +Default: +
                      None<Btn3Down>:  Select(ToggleObject)
            +          None<Btn3Down>,None<Btn3Motion>: See resource file - this is complex
            +
            +

            SetFlag(Object|SelectElements|SelectedPins|SelectedVias|Selected,thermal|octagon|square)
            Sets the indicated flag. This adds thermals, sets the flag +which indicates a pin/pad should be square, or sets the flag which +indicates a pin/pad should be octagonal. +
                      :SetFlag(Selected,thermal)
            +
            +


            SetValue(Grid|LineSize|TextScale|ViaDrillingHole|ViaSize|Zoom, value)
            Some internal values may be changed online by this function. +The first parameter specifies which data has to be changed. The other one +determines if the resource is set to the passed value, if value is +specified without sign, or increments/decrements if it is specified with +a plus or minus sign. +The function doesn't change any existing object only the initial values of +new objects. Use the ChangeSize() and ChangeDrillSize() +to change existing objects. +Default: +
                      None<Key>g:        SetValue(Grid, +5)
            +          !Shift<Key>g:      SetValue(Grid, -5)
            +          None<Key>l:        SetValue(LineSize, +5)
            +          !Shift<Key>l:      SetValue(LineSize, -5)
            +          None<Key>t:        SetValue(TextScale, +10)
            +          !Shift<Key>t:      SetValue(TextScale, -10)
            +          None<Key>v:        SetValue(ViaSize, +5)
            +          !Shift<Key>v:      SetValue(ViaSize, -5)
            +          !Mod1<Key>v:       SetValue(ViaDrillingHole, +5)
            +          !Mod1 Shift<Key>v: SetValue(ViaDrillingHole, -5)
            +          None<Key>z:        SetValue(Zoom, -1)
            +          !Shift<Key>z:      SetValue(Zoom, +1)
            +
            +


            SwapSides()
            This routine changes the board side you are viewing. +Default: +
                      None<Key>Tab:      SwapSides()
            +
            +


            SwitchDrawingLayer(value)
            Makes layer number 1..MAX_LAYER the current one. +Default: +
                      None<Key>1:        SwitchDrawingLayer(1)
            +          ...
            +          None<Key>MAX_LAYER:        SwitchDrawingLayer(MAX_LAYER)
            +
            +


            ToggleHideName(Object|SelectedElements)
            Toggles whether the element's name is displayed or hidden. If it +is hidden you won't see it on the screen and it will not appear +on the silk layer when you print the layout. +
                      None<Key>h:	ToggleHideName(Object)
            +          !Shift<Key>h:	ToggleHideName(SelectedElements)
            +
            +


            ToggleVendor()
            Toggles automatic drill size mapping to the loaded vendor drill table. +
                      ToggleVendor()
            +
            +


            ToggleVisibility(Layer)
            Toggles the visibility of the layer. +
                      Mod1<Key>1:	ToggleVisibility(1)
            +          Mod1<Key>2:	ToggleVisibility(2)
            +          Mod1<Key>3:	ToggleVisibility(3)
            +          Mod1<Key>4:	ToggleVisibility(4)
            +
            +


            Undo()
            Undo(ClearList)
            The unlimited undo feature of pcb-rnd allows you to recover +from most operations that materially affect you work. +Calling 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. +Default: +
                      None<Key>u:        Undo()
            +          !Shift Ctrl<Key>u: Undo(ClearList)
            +
            +


            UnloadVendor()
            Unloads the loaded vendor drill table. +
                      UnloadVendor()
            +
            +


            Unselect(All|Block|Connection)
            Unselects all visible objects, all inside a rectangle or all objects which +have been found during the last connection scan. +Default: +
                      !Shift <Btn3Down>: Mode(Save) Mode(None) Unselect(Block)
            +          !Shift <Btn3Up>:   Unselect(Block) Mode(Restore)
            +
            +
            + +
            + +


            +Previous: Actions, +Up: X11 Interface + +
            + +

            7.3 Default Translations

            + +

            +This section covers some default translations of key and button events as +defined in the shipped default application resource file. Most of them have +already been listed in Actions. pcb-rnd makes use of a nice X11 +feature; calling several action routines for one event. + + + + + + +

            None<Key>BackSpace:
            None<key>Delete:
            !Shift<Key>BackSpace:
            !Shift Ctrl<Btn1>:
            The object at the cursor location is removed by None<Key>BackSpace or +Shift Ctrl<Btn1> whereas Shift<Key>BackSpace also removes +all other objects that are fully-connected to the one at the cursor location. + +


            !Mod1 Ctrl<Key>Left:
            !Mod1 Ctrl<Key>Right:
            !Mod1 Ctrl<Key>Up:
            !Mod1 Ctrl<Key>Down:
            Scroll one page in one of the four directions. + +


            None<Key>Left:, !Shift<Key>Left:
            None<Key>Right:, !Shift<Key>Right:
            None<Key>Up:, !Shift<Key>Up:
            None<Key>Down:, !Shift<Key>Down:
            Move cross hair either one or ten points in grid. + +


            None<Key>Return:
            Finished user input, selects the 'default' button of dialogs. + +


            None<Key>Escape:
            Mode(Reset), aborts user input, selects the 'abort' button of +dialogs or resets all modes. + +


            None<Btn2Down>, Btn2<Motion>, None<Btn2Up>:
            !Mod1<Btn2Down>, Btn2<Motion>, !Mod1<Btn2Up>:
            The first sequence moves the object or element name at the cursor location. +The second one copies the objects. Copying isn't available for +element names. + +
            + + +
            + +


            +Next: , +Previous: X11 Interface, +Up: Top + +
            + +

            7 File Formats

            + +

            +All files used by pcb-rnd are read from the standard output of a command +or written to the standard input of one as plain seven bit ASCII. This +makes it possible to use any editor to change the contents of a layout file. +It is the only way for element or font description files to be created. +To do so you'll need to study the example files example/* and +default_font which are shipped with pcb-rnd. +For an overview refer to Intro. + +

            The following sections provide the necessary information about the syntax of +the files. +Netlist files are not created by pcb-rnd, but it does use them. For information +on the format of a netlist file see the :rn, +User Commands. +The commands described allow you to add almost any additional +functionality you may need. Examples are compressed read and write access as +well as archives. The commands themselves are defined by the resources +elementCommand, fileCommand, fontCommand, +libraryCommand, libraryContentsCommand and saveCommand. +Note that the commands are not saved along with the data. +It is considered an advantage to have the layout file contain all necessary +information, independent of any other files. + +

            One thing common to all files is they may include comments, newlines, +and carriage returns at any place except within quoted strings. + +

            + +
            + +


            +Next: , +Up: File Formats + +
            + +

            8.1 Pad and Line Representation

            + +

            +Pads and lines (copper traces, silk screen lines, etc) are represented by the +line end points and the aperture used to draw the line. It is important to +understand this when creating the pads for a new footprint. The following figure +illustrates a pad or line which is drawn using a square aperture. The end +points (X0,Y0), (X1,Y1) specify the center of the aperture. The size parameter +specifies the size of the aperture. + +

            Pad Layout
            + +

            Pads and lines are represented in this way because this is how lines are +specified in RS-274X (Gerber) files which are used for creating +the masks used in board manufacturing. In fact, older mask making +equipment created lines in precisely this fashion. A physical aperture was +used to pass light through onto a photosensitive film. + +

            + +


            +Next: , +Previous: Pad and Line Representation, +Up: File Formats + +
            + +

            8.2 Layout File Format

            + +

            +The layout file describes a complete layout including symbols, vias, +elements and layers with lines, rectangles and text. This is the most +complex file of all. As pcb-rnd has evolved, the file format has +changed several times to accommodate new features. pcb-rnd has +always been able to read all older versions of the .pcb file. +This allows the migration of older designs to newer versions of the +program. Obviously older versions of pcb-rnd will not be able +to properly read layout files stored in newer versions of the file +format. + +

            In practice it is very common for footprint libraries to contain +elements which have been defined in various versions of the pcb-rnd +file format. When faced with trying to understand an element file or +layout file which includes syntax not defined here, the best approach +is to examine the file src/parse_y.y which is the definitive +definition of the file format. + +

            The PCB layout file contains the following contents, in this order (individual items +are defined in File Syntax: + +

            +
            PCB
            This names the board and sets its size + +
            Grid
            Optional. + +
            Cursor
            Optional. + +
            Flags
            Optional. + +
            Groups
            Optional. + +
            Styles
            Optional. + +
            Symbols
            Optional. + +
            Vias, Rats, Layers, and Elements
            These may occur in any order, at this point in the file. + +
            Netlists
            Optional. + +
            + +
            + +


            +Next: , +Previous: Layout File, +Up: File Formats + +
            + +

            8.3 Element File Format

            + +

            +Element files are used to describe one component which then may be used +several times within one or more layouts. You will normally split the +file into two parts, one for the pinout and one for the package description. +Using m4 allows you to define pin names as macros in one file and +include a package description file which evaluates the macros. See +the resource elementCommand for more information. The pins (and pads) +must appear in sequential order in the element file (new in 1.5) so that +pin 1 must be the first PIN(...) in the file. + +

            Doing things this way makes it possible to use one package file for several +different circuits. See the sample files dil*. + +

            The lowest x and y coordinates of all sub-objects of an element are +used as an attachment point for the cross hair cursor of the main +window, unless the element has a mark, in which case that's the +attachment point. + +

            + +


            +Next: , +Previous: Element File, +Up: File Formats + +
            + +

            8.4 Font File Format

            + +

            +A number of user defined Symbols are called a font. There is only one per +layout. All symbols are made of lines. See the file default_font +as an example. + +

            The lowest x and y coordinates of all lines of a font are transformed to (0,0). + +

            + +


            +Next: , +Previous: Font File, +Up: File Formats + +
            + +

            8.5 Netlist File Format

            + +

            +Netlists read by pcb-rnd must have this simple text form: + +

                 netname [style] NAME-PINNUM NAME2-PINNUM2 NAME3-PINNUM3 ... [\]
            +
            +

            for each net on the layout. +where "netname" is the name of the net which must be unique for each +net, [style] is an optional route-style name, +NAME is the layout-name name given to an element, +and PINNUM is the (usually numeric) +pin number of the element that connects to the net +(for details on pin numbering see Element Objects). +Spaces or tabs separate the fields. +If the line ends with a "\" the +net continues on the next line and the "\" is treated exactly as if it +were a space. If a NAME ends with a lower-case letter, +all lower-case letters are stripped from the end of the NAME to determine the +matching layout-name name. For example: + +

                      Data U1-3 U2abc-4 FLOP1a-7 Uabc3-A9
            +
            +

            specifies that the net called "Data" should have +pin 3 of U1 connected to pin 4 of U2, to pin 7 of +FLOP1 and to pin A9 of Uabc3. Note that element name and +pin number strings are case-sensitive. +It is up to you to name the elements so that their layout-name names +agrees with the netlist. + +

            + +


            +Next: , +Previous: Netlist File, +Up: File Formats + +
            + +

            8.6 Library Contents File Format

            + +

            +There is nothing like a special library format. The ones that have been +introduced in 1.4.1 just use some nice (and time consuming) features of GNU +m4. The only predefined format is the one of the contents file +which is read during startup. It is made up of two basic line types: + +

                 menu entry      = "TYPE="name
            +     contents line   = template":"package":"value":"description
            +     name            = String
            +     template        = String
            +     package         = String
            +     value           = String
            +     description     = String
            +     String          = <anything except ":", "\n" and "\r">
            +
            +

            No leading white spaces or comments are allowed in this file. If you need +either one, define a command that removes them before loading. Have a look +to the libraryContentsCommand resource. + +

            The menu entry will appear in the selection menu at the top and of the +library window. + +

            + +


            +Next: , +Previous: Library Contents File, +Up: File Formats + +
            + +

            8.7 Library File Format

            + +

            +This section provides an overview about the existing m4 definitions +of the elements. There are basically two different types of files. One +to define element specific data like the pinout, package and so on, the +other to define the values. For example the static RAM circuits 43256 and +62256 are very similar. They therefore share a common definition in the +macro file but are defined with two different value labels. + +

            The macro file entry: +

                 define(`Description_43256_dil', `SRAM 32Kx8')
            +     define(`Param1_43256_dil', 28)
            +     define(`Param2_43256_dil', 600)
            +     define(`PinList_43256_dil', ``pin1', `pin2', ...')
            +
            +

            And the list file: +

                 43256_dil:N:43256:62256
            +
            +

            The macro must define a description, the pin list and up to two additional +parameters that are passed to the package definitions. The first one is +the number of pins whereas the second one defines for example the width +of a package. + +

            It is very important to select a unique identifier for each macro. In +the example this would be 43256_dil which is also the templates name. +It is required by some low-level macros that +Description_, Param1_, Param2_ and PinList_ are perpended. + +

            The list file uses a syntax: +

                 template:package:value[:more values]
            +
            +

            This means that the shown example will create two element entries with the +same package and pinout but with different names. + +

            A number of packages are defined in common.m4. Included are: + +

                 DIL packages with suffix D, DW, J, JD, JG, N, NT, P
            +     PLCC
            +     TO3
            +     generic connectors
            +     DIN 41.612 connectors
            +     zick-zack (SD suffix)
            +     15 pin multiwatt
            +
            +

            If you are going to start your own library please take care about m4 +functions. Be aware of quoting and so on and, most important check your +additional entry by calling the macro: + +

                 CreateObject(`template', `value', `package suffix')
            +
            +

            If quoting is incorrect an endless loop may occur (broken by a out-of-memory +message). + +

            The scripts in the lib directory handle the creation of libraries +as well as of their contents files. Querying is also supported. + +

            I know quite well that this description of the library implementation is +not what some out there expect. But in my opinion it's much more useful to +look at the comments and follow the macros step by step. + +

            + +


            +Next: , +Previous: Library File, +Up: File Formats + +
            + +

            8.8 File Syntax

            + +

            + + + +

            A special note about units: Older versions of pcb used mils +(1/1000 inch) as the base unit; a value of 500 in the file meant +half an inch. Newer versions uses a "high resolution" syntax, +where the base unit is 1/100 of a mil (0.000010 inch); a value of 500 in +the file means 5 mils. As a general rule, the variants of each entry +listed below which use square brackets are the high resolution formats +and use the 1/100 mil units, and the ones with parentheses are the older +variants and use 1 mil units. Note that when multiple variants +are listed, the most recent (and most preferred) format is the first +listed. + +

            Symbolic and numeric flags (SFlags and NFlags) are described in +Object Flags. + +

            + +
            + +


            +Next: , +Up: File Syntax + +
            + +

            8.8.1 Arc

            + + +

            +
            Arc [X Y Width Height Thickness Clearance StartAngle DeltaAngle SFlags]
            +Arc (X Y Width Height Thickness Clearance StartAngle DeltaAngle NFlags)
            +Arc (X Y Width Height Thickness StartAngle DeltaAngle NFlags)
            +
            +
            + +

            +
            X Y
            Coordinates of the center of the arc. +
            Width Height
            The width and height, from the center to the edge. The bounds of the +circle of which this arc is a segment, is thus 2*Width by +2*Height. +
            Thickness
            The width of the copper trace which forms the arc. +
            Clearance
            The amount of space cleared around the arc when the line passes +through a polygon. The clearance is added to the thickness to get the +thickness of the clear; thus the space between the arc and the polygon +is Clearance/2 wide. +
            StartAngle
            The angle of one end of the arc, in degrees. In PCB, an angle of zero +points left (negative X direction), and 90 degrees points down +(positive Y direction). +
            DeltaAngle
            The sweep of the arc. This may be negative. Positive angles sweep +counterclockwise. +
            SFlags
            Symbolic or numeric flags. +
            NFlags
            Numeric flags. +
            + + +
            + +


            +Next: , +Previous: Arc syntax, +Up: File Syntax + +
            + +

            8.8.2 Attribute

            + + +

            +
            Attribute ("Name" "Value")
            +
            +
            + +

            Attributes allow boards and elements to have arbitrary data attached +to them, which is not directly used by PCB itself but may be of use by +other programs or users. + +

            +
            Name
            The name of the attribute + +
            Value
            The value of the attribute. Values are always stored as strings, even +if the value is interpreted as, for example, a number. + +
            + + +
            + +


            +Next: , +Previous: Attribute syntax, +Up: File Syntax + +
            + +

            8.8.3 Connect

            + + +

            +
            Connect ("PinPad")
            +
            +
            + +

            +
            PinPad
            The name of a pin or pad which is included in this net. Pin and Pad +names are named by the refdes and pin name, like "U14-7" for +pin 7 of U14, or "T4-E" for pin E of T4. +
            + + +
            + +


            +Next: , +Previous: Connect syntax, +Up: File Syntax + +
            + +

            8.8.4 Cursor

            + + +

            +
            Cursor [X Y Zoom]
            +Cursor (X Y Zoom)
            +
            +
            + +

            +
            X Y
            Location of the cursor when the board was saved. +
            Zoom
            The current zoom factor. Note that a zoom factor of "0" means 1 mil +per screen pixel, N means 2^N mils per screen pixel, etc. The +first variant accepts floating point numbers. The special value +"1000" means "zoom to fit" +
            + + +
            + +


            +Next: , +Previous: Cursor syntax, +Up: File Syntax + +
            + +

            8.8.5 DRC

            + + +

            +
            DRC [Bloat Shrink Line Silk Drill Ring]
            +DRC [Bloat Shrink Line Silk]
            +DRC [Bloat Shrink Line]
            +
            +
            + +

            +
            Bloat
            Minimum spacing between copper. +
            Shrink
            Minimum copper overlap to guarantee connectivity. +
            Line
            Minimum line thickness. +
            Silk
            Minimum silk thickness. +
            Drill
            Minimum drill size. +
            Ring
            Minimum width of the annular ring around pins and vias. +
            + + +
            + +


            +Next: , +Previous: DRC syntax, +Up: File Syntax + +
            + +

            8.8.6 Element

            + + +

            +
            Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] (
            +Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) (
            +Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) (
            +Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) (
            +Element ("Desc" "Name" TX TY TDir TScale TNFlags) (
            +   ... contents ...
            +)
            +
            +
            + +

            +
            SFlags
            Symbolic or numeric flags, for the element as a whole. +
            NFlags
            Numeric flags, for the element as a whole. +
            Desc
            The description of the element. This is one of the three strings +which can be displayed on the screen. +
            Name
            The name of the element, usually the reference designator. +
            Value
            The value of the element. +
            MX MY
            The location of the element's mark. This is the reference point +for placing the element and its pins and pads. +
            TX TY
            The upper left corner of the text (one of the three strings). +
            TDir
            The relative direction of the text. 0 means left to right for +an unrotated element, 1 means up, 2 left, 3 down. +
            TScale
            Size of the text, as a percentage of the “default” size of of the +font (the default font is about 40 mils high). Default is 100 (40 +mils). +
            TSFlags
            Symbolic or numeric flags, for the text. +
            TNFlags
            Numeric flags, for the text. +
            + +

            Elements may contain pins, pads, element lines, element arcs, +attributes, and (for older elements) an optional mark. Note that +element definitions that have the mark coordinates in the element +line, only support pins and pads which use relative coordinates. The +pin and pad coordinates are relative to the mark. Element definitions +which do not include the mark coordinates in the element line, may +have a Mark definition in their contents, and only use pin and pad +definitions which use absolute coordinates. + + +

            + +


            +Next: , +Previous: Element syntax, +Up: File Syntax + +
            + +

            8.8.7 ElementArc

            + + +

            +
            ElementArc [X Y Width Height StartAngle DeltaAngle Thickness]
            +ElementArc (X Y Width Height StartAngle DeltaAngle Thickness)
            +
            +
            + +

            +
            X Y
            Coordinates of the center of the arc. These are relative to the +Element's mark point for new element formats, or absolute for older +formats. +
            Width Height
            The width and height, from the center to the edge. The bounds of the +circle of which this arc is a segment, is thus 2*Width by +2*Height. +
            StartAngle
            The angle of one end of the arc, in degrees. In PCB, an angle of zero +points left (negative X direction), and 90 degrees points down +(positive Y direction). +
            DeltaAngle
            The sweep of the arc. This may be negative. Positive angles sweep +counterclockwise. +
            Thickness
            The width of the silk line which forms the arc. +
            + + +
            + +


            +Next: , +Previous: ElementArc syntax, +Up: File Syntax + +
            + +

            8.8.8 ElementLine

            + + +

            +
            ElementLine [X1 Y1 X2 Y2 Thickness]
            +ElementLine (X1 Y1 X2 Y2 Thickness)
            +
            +
            + +

            +
            X1 Y1 X2 Y2
            Coordinates of the endpoints of the line. These are relative to the +Element's mark point for new element formats, or absolute for older +formats. +
            Thickness
            The width of the silk for this line. +
            + + +
            + +


            +Next: , +Previous: ElementLine syntax, +Up: File Syntax + +
            + +

            8.8.9 FileVersion

            + + +

            +
            FileVersion[Version]
            +
            +
            + +

            +
            Version
            File format version. This version number represents the date when the pcb file +format was last changed. +
            + +

            Any version of pcb build from sources equal to or newer +than this number should be able to read the file. If this line is not present +in the input file then file format compatibility is not checked. + + +

            + +


            +Next: , +Previous: FileVersion syntax, +Up: File Syntax + +
            + +

            8.8.10 Flags

            + + +

            +
            Flags(Number)
            +
            +
            + +

            +
            Number
            A number, whose value is normally given in hex, individual bits of which +represent pcb-wide flags as defined in PCBFlags. + +
            + + +
            + +


            +Next: , +Previous: Flags syntax, +Up: File Syntax + +
            + +

            8.8.11 Grid

            + + +

            +
            Grid [Step OffsetX OffsetY Visible]
            +Grid (Step OffsetX OffsetY Visible)
            +Grid (Step OffsetX OffsetY)
            +
            +
            + +

            +
            Step
            Distance from one grid point to adjacent points. This value may be a +floating point number for the first two variants. +
            OffsetX OffsetY
            The "origin" of the grid. Normally zero. +
            Visible
            If non-zero, the grid will be visible on the screen. +
            + + +
            + +


            +Next: , +Previous: Grid syntax, +Up: File Syntax + +
            + +

            8.8.12 Groups

            + + +

            +
            Groups("String")
            +
            +
            + +

            +
            String
            +Encodes the layer grouping information. Each group is separated by a +colon, each member of each group is separated by a comma. Group +members are either numbers from 1..N for each layer, and +the letters c or s representing the component side and +solder side of the board. Including c or s marks that +group as being the top or bottom side of the board. + +
                      Groups("1,2,c:3:4:5,6,s:7,8")
            +
            +
            + + +
            + +


            +Next: , +Previous: Groups syntax, +Up: File Syntax + +
            + +

            8.8.13 Layer

            + + +

            +
            Layer (LayerNum "Name") (
            +   ... contents ...
            +)
            +
            +
            + +

            +
            LayerNum
            The layer number. Layers are numbered sequentially, starting with 1. +The last two layers (9 and 10 by default) are solder-side silk and +component-side silk, in that order. +
            Name
            The layer name. +
            contents
            The contents of the layer, which may include attributes, lines, arcs, rectangles, +text, and polygons. +
            + + +
            + +


            +Next: , +Previous: Layer syntax, +Up: File Syntax + +
            + +

            8.8.14 Line

            + + +

            +
            Line [X1 Y1 X2 Y2 Thickness Clearance SFlags]
            +Line (X1 Y1 X2 Y2 Thickness Clearance NFlags)
            +Line (X1 Y1 X2 Y2 Thickness NFlags)
            +
            +
            + +

            +
            X1 Y1 X2 Y2
            The end points of the line +
            Thickness
            The width of the line +
            Clearance
            The amount of space cleared around the line when the line passes +through a polygon. The clearance is added to the thickness to get the +thickness of the clear; thus the space between the line and the +polygon is Clearance/2 wide. +
            SFlags
            Symbolic or numeric flags +
            NFlags
            Numeric flags. +
            + + +
            + +


            +Next: , +Previous: Line syntax, +Up: File Syntax + +
            + +

            8.8.15 Mark

            + + +

            +
            Mark [X Y]
            +Mark (X Y)
            +
            +
            + +

            +
            X Y
            Coordinates of the Mark, for older element formats that don't have +the mark as part of the Element line. +
            + + +
            + +


            +Next: , +Previous: Mark syntax, +Up: File Syntax + +
            + +

            8.8.16 Net

            + + +

            +
            Net ("Name" "Style") (
            +   ... connects ...
            +)
            +
            +
            + +

            +
            Name
            The name of this net. +
            Style
            The routing style that should be used when autorouting this net. +
            + + +
            + +


            +Next: , +Previous: Net syntax, +Up: File Syntax + +
            + +

            8.8.17 Netlist

            + + +

            +
            Netlist ( ) (
            +   ... nets ...
            +)
            +
            +
            + + +

            + +


            +Next: , +Previous: Netlist syntax, +Up: File Syntax + +
            + +

            8.8.18 Pad

            + + +

            +
            Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags]
            +Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags)
            +Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags)
            +Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags)
            +
            +
            + +

            +
            rX1 rY1 rX2 rY2
            Coordinates of the endpoints of the pad, relative to the element's +mark. Note that the copper extends beyond these coordinates by half +the thickness. To make a square or round pad, specify the same +coordinate twice. +
            aX1 aY1 aX2 aY2
            Same, but absolute coordinates of the endpoints of the pad. +
            Thickness
            width of the pad. +
            Clearance
            add to thickness to get clearance width. +
            Mask
            width of solder mask opening. +
            Name
            name of pin +
            Number
            number of pin +
            SFlags
            symbolic or numerical flags +
            NFlags
            numerical flags only +
            + + +
            + +


            +Next: , +Previous: Pad syntax, +Up: File Syntax + +
            + +

            8.8.19 PCB

            + + +

            +
            PCB ["Name" Width Height]
            +PCB ("Name" Width Height]
            +PCB ("Name")
            +
            +
            + +

            +
            Name
            Name of the PCB project +
            Width Height
            Size of the board +
            + +

            If you don't specify the size of the board, a very large default is +chosen. + + +

            + +


            +Next: , +Previous: PCB syntax, +Up: File Syntax + +
            + +

            8.8.20 Pin

            + + +

            +
            Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags]
            +Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags)
            +Pin (aX aY Thickness Drill "Name" "Number" NFlags)
            +Pin (aX aY Thickness Drill "Name" NFlags)
            +Pin (aX aY Thickness "Name" NFlags)
            +
            +
            + +

            +
            rX rY
            coordinates of center, relative to the element's mark +
            aX aY
            absolute coordinates of center. +
            Thickness
            outer diameter of copper annulus +
            Clearance
            add to thickness to get clearance diameter +
            Mask
            diameter of solder mask opening +
            Drill
            diameter of drill +
            Name
            name of pin +
            Number
            number of pin +
            SFlags
            symbolic or numerical flags +
            NFlags
            numerical flags only +
            + + +
            + +


            +Next: , +Previous: Pin syntax, +Up: File Syntax + +
            + +

            8.8.21 PolyArea

            + + +

            +
            PolyArea [Area]
            +
            +
            + +

            +
            Area
            Minimum area of polygon island to retain. If a polygon has clearances that cause an isolated island to be created, then will only be retained if the area exceeds this minimum area. +
            + + +
            + +


            +Next: , +Previous: PolyArea syntax, +Up: File Syntax + +
            + +

            8.8.22 Polygon

            + + +

            +
            Polygon (SFlags) (
            +   ... (X Y) ...
            +   ... [X Y] ...
            +   Hole (
            +      ... (X Y) ...
            +      ... [X Y] ...
            +   )
            +   ...
            +)
            +
            +
            + +

            +
            SFlags
            Symbolic or numeric flags. +
            X Y
            Coordinates of each vertex. You must list at least three coordinates. +
            Hole (...)
            Defines a hole within the polygon's outer contour. There may be zero or more such sections. +
            + + +
            + +


            +Next: , +Previous: Polygon syntax, +Up: File Syntax + +
            + +

            8.8.23 Rat

            + + +

            +
            Rat [X1 Y1 Group1 X2 Y2 Group2 SFlags]
            +Rat (X1 Y1 Group1 X2 Y2 Group2 NFlags)
            +
            +
            + +

            +
            X1 Y1 X2 Y2
            The endpoints of the rat line. +
            Group1 Group2
            The layer group each end is connected on. +
            SFlags
            Symbolic or numeric flags. +
            NFlags
            Numeric flags. +
            + + +
            + +


            +Next: , +Previous: Rat syntax, +Up: File Syntax + +
            + +

            8.8.24 Styles

            + + +

            +
            Styles("String")
            +
            +
            + +

            +
            String
            +Encodes the four routing styles pcb knows about. The four styles +are separated by colons. Each style consists of five parameters as follows: + +
            +
            Name
            The name of the style. +
            Thickness
            Width of lines and arcs. +
            Diameter
            Copper diameter of pins and vias. +
            Drill
            Drill diameter of pins and vias. +
            Keepaway
            Minimum spacing to other nets. If omitted, 10 mils is the default. + +
            + +
            + +
                 Styles("Signal,10,40,20:Power,25,60,35:Fat,40,60,35:Skinny,8,36,20")
            +     Styles["Logic,1000,3600,2000,1000:Power,2500,6000,3500,1000:
            +        Line,4000,6000,3500,1000:Breakout,600,2402,1181,600"]
            +
            +

            Note that strings in actual files cannot span lines; the above example +is split across lines only to make it readable. + + +

            + +


            +Next: , +Previous: Styles syntax, +Up: File Syntax + +
            + +

            8.8.25 Symbol

            + + +

            +
            Symbol [Char Delta] (
            +Symbol (Char Delta) (
            +   ... symbol lines ...
            +)
            +
            +
            + +

            +
            Char
            The character or numerical character value this symbol represents. +Characters must be in single quotes. +
            Delta
            Additional space to allow after this character. +
            + + +
            + +


            +Next: , +Previous: Symbol syntax, +Up: File Syntax + +
            + +

            8.8.26 SymbolLine

            + + +

            +
            SymbolLine [X1 Y1 X2 Y1 Thickness]
            +SymbolLine (X1 Y1 X2 Y1 Thickness)
            +
            +
            + +

            +
            X1 Y1 X2 Y2
            The endpoints of this line. +
            Thickness
            The width of this line. +
            + + +
            + +


            +Next: , +Previous: SymbolLine syntax, +Up: File Syntax + +
            + +

            8.8.27 Text

            + + +

            +
            Text [X Y Direction Scale "String" SFlags]
            +Text (X Y Direction Scale "String" NFlags)
            +Text (X Y Direction "String" NFlags)
            +
            +
            + +

            +
            X Y
            The location of the upper left corner of the text. +
            Direction
            0 means text is drawn left to right, 1 means up, 2 means right to left +(i.e. upside down), and 3 means down. +
            Scale
            Size of the text, as a percentage of the “default” size of of the +font (the default font is about 40 mils high). Default is 100 (40 +mils). +
            String
            The string to draw. +
            SFlags
            Symbolic or numeric flags. +
            NFlags
            Numeric flags. +
            + + +
            + +


            +Next: , +Previous: Text syntax, +Up: File Syntax + +
            + +

            8.8.28 Thermal

            + + +

            +
            Thermal [Scale]
            +
            +
            + +

            +
            Scale
            Relative size of thermal fingers. A value of 1.0 makes the finger +width twice the clearance gap width (measured across the gap, not +diameter). The normal value is 0.5, which results in a finger width +the same as the clearance gap width. +
            + + +
            + +


            +Previous: Thermal syntax, +Up: File Syntax + +
            + +

            8.8.29 Via

            + + +

            +
            Via [X Y Thickness Clearance Mask Drill "Name" SFlags]
            +Via (X Y Thickness Clearance Mask Drill "Name" NFlags)
            +Via (X Y Thickness Clearance Drill "Name" NFlags)
            +Via (X Y Thickness Drill "Name" NFlags)
            +Via (X Y Thickness "Name" NFlags)
            +
            +
            + +

            +
            X Y
            coordinates of center +
            Thickness
            outer diameter of copper annulus +
            Clearance
            add to thickness to get clearance diameter +
            Mask
            diameter of solder mask opening +
            Drill
            diameter of drill +
            Name
            string, name of via (vias have names?) +
            SFlags
            symbolic or numerical flags +
            NFlags
            numerical flags only +
            + + + +
            + +


            +Next: , +Previous: File Syntax, +Up: File Formats + +
            + +

            8.9 Object Flags

            + +

            Note that object flags can be given numerically (like 0x0147) +or symbolically (like "found,showname,square". Some numeric +values are reused for different object types. The table below lists +the numeric value followed by the symbolic name. + +

            +
            0x0001 pin
            If set, this object is a pin. This flag is for internal use only. +
            0x0002 via
            Likewise, for vias. +
            0x0004 found
            If set, this object has been found by FindConnection(). +
            0x0008 hole
            For pins and vias, this flag means that the pin or via is a hole +without a copper annulus. +
            0x0010 rat
            If set for a line, indicates that this line is a rat line instead of a +copper trace. +
            0x0010 pininpoly
            For pins and pads, this flag is used internally to indicate that the +pin or pad overlaps a polygon on some layer. +
            0x0010 clearpoly
            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. +
            0x0010 hidename
            For elements, when set the name of the element is hidden. +
            0x0020 showname
            For elements, when set the names of pins are shown. +
            0x0020 clearline
            For lines and arcs, the line/arc will clear polygons instead of +connecting to them. +
            0x0020 fullpoly
            For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one). +
            0x0040 selected
            Set when the object is selected. +
            0x0080 onsolder
            For elements and pads, indicates that they are on the solder side. +
            0x0080 auto
            For lines and vias, indicates that these were created by the +autorouter. +
            0x0100 square
            For pins and pads, indicates a square (vs round) pin/pad. +
            0x0200 rubberend
            For lines, used internally for rubber band moves. +
            0x0200 warn
            For pins, vias, and pads, set to indicate a warning. +
            0x0400 usetherm
            Obsolete, indicates that pins/vias should be drawn with thermal +fingers. +
            0x0400
            Obsolete, old files used this to indicate lines drawn on silk. +
            0x0800 octagon
            Draw pins and vias as octagons. +
            0x1000 drc
            Set for objects that fail DRC. +
            0x2000 lock
            Set for locked objects. +
            0x4000 edge2
            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. +
            0x8000 marker
            Marker used internally to avoid revisiting an object. +
            0x10000 nopaste
            For pads, set to prevent a solderpaste stencil opening for the +pad. Primarily used for pads used as fiducials. +
            + + +
            + +


            +Previous: Object Flags, +Up: File Formats + +
            + +

            8.10 PCBFlags

            + +
            +
            0x00001
            Pinout displays pin numbers instead of pin names. +
            0x00002
            Use local reference for moves, by setting the mark at the beginning of +each move. +
            0x00004
            When set, only polygons and their clearances are drawn, to see if +polygons have isolated regions. +
            0x00008
            Display DRC region on crosshair. +
            0x00010
            Do all move, mirror, rotate with rubberband connections. +
            0x00020
            Display descriptions of elements, instead of refdes. +
            0x00040
            Display names of elements, instead of refdes. +
            0x00080
            Auto-DRC flag. When set, PCB doesn't let you place copper that +violates DRC. +
            0x00100
            Enable 'all-direction' lines. +
            0x00200
            Switch starting angle after each click. +
            0x00400
            Force unique names on board. +
            0x00800
            New lines/arc clear polygons. +
            0x01000
            Crosshair snaps to pins and pads. +
            0x02000
            Show the solder mask layer. +
            0x04000
            Draw with thin lines. +
            0x08000
            Move items orthogonally. +
            0x10000
            Draw autoroute paths real-time. +
            0x20000
            New polygons are full ones. +
            0x40000
            Names are locked, the mouse cannot select them. +
            0x80000
            Everything but names are locked, the mouse cannot select anything else. +
            0x100000
            New polygons are full polygons. +
            0x200000
            When set, element names are not drawn. +
            + + +
            + +


            +Next: , +Previous: File Formats, +Up: Top + +
            + +

            8 Library Creation

            + +

            +This chapter provides a detailed look at how footprint libraries are +created and used. + +

            pcb-rnd footprint libraries store each footprint in its own +file. The footprints are created graphically by placing pads and then +converting a group of pads to a component. This library method has the +advantage of being quick to learn and it is easily to build single +footprints quickly. If you are building a family of parts, however, the +additional effort in creating each one individually makes this approach +undesirable. In addition, creating a part with a large pin count +can be quite tedious when done by hand. + +

            9.1 Old Style (m4) Libraries

            + +

            The old style libraries for pcb use the m4 macro processor to +allow the definition of a family of parts. There are several files +associated with the old style library. The file common.m4 is the +top level file associated with the library. common.m4 defines a +few utility macros which are used by other portions of the library, +and then includes a predefined set of library files (the lines like +include(geda.inc)). + +

            9.1.1 Overview of Oldlib Operation

            + +

            The big picture view of the old style library system is that the library +is simply a collection of macro definitions. The macros are written in +the m4 macro language. An example of a macro and what it expands +to is the following. One of the predefined footprints in the library +which comes with PCB is the PKG_SO8 macro. Note that all the +footprint macros begin with PKG_. For this particular example, +PKG_SO8 is a macro for an 8-pin small outline surface mount +package. All of the footprint macros take 3 arguments. The first is the +canonical name of the footprint on the board. In this case "SO8" is an +appropriate name. The second argument is the reference designator on +the board such as "U1" or "U23". The third and final argument is the +value. For an integrated circuit this is usually the part number such +as "MAX4107" or "78L05" and for a component such as a resistor or +capacitor it is the resistance or capacitance. The complete call to the +macro in our example is ‘PKG_SO8(SO8, U1, MAX4107)’. When +processed by m4 using the macros defined in the PCB library, this +macro expands to +

                 Element(0x00 "SO8" "U1" "MAX4107" 146 50 3 100 0x00)
            +     (
            +     	Pad(10 25 38 25 20 "1" 0x00)
            +     	Pad(10 75 38 75 20 "2" 0x100)
            +     	Pad(10 125 38 125 20 "3" 0x100)
            +     	Pad(10 175 38 175 20 "4" 0x100)
            +     	Pad(214 175 242 175 20 "5" 0x100)
            +     	Pad(214 125 242 125 20 "6" 0x100)
            +     	Pad(214 75 242 75 20 "7" 0x100)
            +     	Pad(214 25 242 25 20 "8" 0x100)
            +     	ElementLine(0 0 151 0 10)
            +     	ElementArc(126 0 25 25 0 180 10)
            +     	ElementLine(101 0 252 0 10)
            +     	ElementLine(252 0 252 200 10)
            +     	ElementLine(252 200 0 200 10)
            +     	ElementLine(0 200 0 0 10)
            +     	Mark(29 25)
            +     )
            +
            +

            which is the actual definition of the footprint that the PCB program +works with. As a user of PCB the only time you will need or want to run +m4 directly is when you are debugging a new library addition. In +normal operation, the calls to m4 are made by helper scripts that +come with PCB. + +

            Tools such as gsch2pcb (used to interface the gEDA schematic +capture program to PCB layout) will call m4 to produce an initial +PCB layout that includes all the components on a schematic. In +addition, when manually instantiating parts from within PCB, m4 +will be called by PCB's helper scripts to produce the footprints. + +

            9.1.2 The Library Scripts

            + +

            There are several scripts that are used for processing the m4 +libraries. This section briefly describes these scripts and details how +they are used by PCB. + +

            9.1.2.1 Scripts Used During Compilation
            + +

            The scripts described in this section are used during compilation of +PCB. They are run automatically by the build system, but are described +here to help document the complete library processing that occurs. +During the build of PCB, the following actions are taken. The +CreateLibrary.sh script is run to produce an M4 "frozen file". +This frozen file is simply a partially processed M4 input file which can +be loaded by M4 more quickly than the original input file. + +

            A typical call to CreateLibrary.sh used during the compilation of +PCB is: +

                 ./CreateLibrary.sh -I . pcblib ./common.m4 TTL_74xx_DIL.m4
            +     connector.m4 crystal.m4 generic.m4 genericsmt.m4 gtag.m4
            +     jerry.m4 linear.m4 logic.m4 lsi.m4 memory.m4 optical.m4 pci.m4
            +     resistor_0.25W.m4 resistor_adjust.m4 resistor_array.m4
            +     texas_inst_amplifier.m4 texas_inst_voltage_reg.m4
            +     transistor.m4 geda.m4
            +
            +

            The ‘-I .’ says to search in the current directory for the +.m4 files. The output frozen file is pcblib. The main +common.m4 file is listed as well as all of the *.m4 files +which define the components in the library. + +

            In addition, a library contents file is created during the build with +the CreateLibraryContents.sh script. +A typical call to CreateLibrary.sh used during the compilation of +PCB is: +

                 ./CreateLibraryContents.sh -I . ./common.m4 TTL_74xx_DIL.list
            +     connector.list crystal.list generic.list genericsmt.list gtag.list
            +     jerry.list linear.list logic.list lsi.list memory.list optical.list
            +     pci.list resistor_0.25W.list resistor_adjust.list resistor_array.list
            +     texas_inst_amplifier.list texas_inst_voltage_reg.list transistor.list
            +     geda.list > pcblib.contents
            +
            +

            The pcblib.contents file is used by the PCB program to define the +libraries and components which will be displayed when you bring up +the library window from within PCB. An example of part of the +pcblib.contents file is: +

                 TYPE=~TTL 74xx DIL
            +     7400_dil:N:7400:4 dual-NAND
            +     7401_dil:N:7401:4 dual-NAND OC
            +     7402_dil:N:7402:4 dual-NOR
            +     TYPE=~geda
            +     geda_DIP6:DIP6:DIP6:Dual in-line package, narrow (300 mil)
            +     geda_DIP8:DIP8:DIP8:Dual in-line package, narrow (300 mil)
            +     geda_DIP14:DIP14:DIP14:Dual in-line package, narrow (300 mil)
            +     geda_ACY300:ACY300:ACY300:Axial non-polar component,
            +
            +

            The TYPE= lines define the library name that will show up in the +library window in PCB. The other lines define the actual components in +the library. + +

            9.1.2.2 Scripts Used by PCB at Runtime
            + +

            When PCB is first executed, it makes a call to the +ListLibraryContents.sh script. This script provides the PCB +program with the contents of the library contents file created when PCB +was compiled. A typical call to ListLibraryContents.sh is +

                 ../lib/ListLibraryContents.sh .:/tmp/pcb-20030903/src/../lib pcblib
            +
            +

            This command says to search the path +‘.:/tmp/pcb-20030903/src/../lib’ for a file called +pcblib.contents (the .contents part is added +automatically) and display the contents of the file. +PCB parses this output and generates the library window entries. + +

            When you pick a library component from the library window, PCB calls the +QueryLibrary.sh script to actually pull the footprint into the +layout. For example, when the ACY300 component is selected from the +~geda library, the generated call may be: + +

                 /tmp/pcb-20030903/src/../lib/QueryLibrary.sh
            +     .:/tmp/pcb-20030903/src/../lib pcblib geda_ACY300 ACY300
            +     ACY300
            +
            +

            If you were to run this command by hand you would see the PCB code for +the element: +

                 Element(0x00 "Axial non-polar component," "" "ACY300" 245 70 0 100 0x00)
            +     (
            +     	Pin(0 25 50 20 "1" 0x101)
            +     	Pin(300 25 50 20 "2" 0x01)
            +     
            +     	ElementLine(0 25 75 25 10)
            +     	ElementLine(225 25 300 25 10)
            +     
            +     	ElementLine(75 0 225 0 10)
            +     	ElementLine(225 0 225 50 10)
            +     	ElementLine(225 50 75 50 10)
            +     	ElementLine(75 50 75 0 10)
            +     
            +     #       ElementArc(X1 Y 50 50 270 180 10)
            +     #       ElementArc(X2 Y 50 50 90 180 10)
            +     
            +     	Mark(75 25)
            +     )
            +
            +

            9.1.3 Creating an Oldlib Footprint

            + +

            This section provides a complete example of defining a family of +footprints using the M4 style library. As a vehicle for this example, a +family of footprints for surface mount resistors and capacitors will be +developed. The file example.inc should have been installed on +your system as $prefix/share/examples/oldlib/example.inc where +$prefix is often times /usr/local. + +

            The example.inc file defines a macro called +COMMON_PKG_RCSMT which is a generic definition for a surface +mount footprint with two identical, rectangular pads. This macro will +be called with different parameters to fill out the family of parts. +The arguments to the COMMON_PKG_RCSMT are: +

                 # -------------------------------------------------------------------
            +     # the definition for surface mount resistors and capacitors
            +     # $1: canonical name
            +     # $2: name on PCB
            +     # $3: value
            +     # $4: pad width   (in direction perpendicular to part)
            +     # $5: pad length  (in direction parallel with part)
            +     # $6: pad spacing (center to center)
            +     # $7: distance from edge of pad to silk (in direction
            +     #     perpendicular to part)
            +     # $8: distance from edge of pad to silk (in direction parallel
            +     #     with part)
            +     # $9: Set to "no" to skip silk screen on the sides of the part
            +
            +
                 define(`COMMON_PKG_RCSMT',
            +     	`define(`XMIN', `eval( -1*`$6'/2 - `$5'/2 - `$8')')
            +     	define(`XMAX', `eval(  `$6'/2 + `$5'/2 + `$8')')
            +     	define(`YMIN', `eval(-1*`$4'/2 - `$7')')
            +     	define(`YMAX', `eval(   `$4'/2 + `$7')')
            +     Element(0x00 "$1" "$2" "$3" eval(XMIN+20) eval(YMAX+20) 0 100 0x00)
            +     (
            +     	ifelse(0, eval($4>$5),
            +     	# Pads which have the perpendicular pad dimension less
            +     	# than or equal to the parallel pad dimension
            +     	Pad(eval(-1*(   $6 + $5 - $4)/2) 0
            +     	    eval((-1*$6 + $5 - $4)/2) 0 eval($4) "1" 0x100)
            +     	Pad(eval(-1*(-1*$6 + $5 - $4)/2) 0
            +     	    eval((   $6 + $5 - $4)/2) 0 eval($4) "2" 0x100)
            +     	,
            +     	# Pads which have the perpendicular pad dimension greater
            +     	# than or equal to the parallel pad dimension
            +     	Pad(eval(-1*$6/2) eval(-1*($4 - $5)/2)
            +     	    eval(-1*$6/2)  eval(($4 - $5)/2) eval($5) "1" 0x100)
            +     	Pad(eval(   $6/2) eval(-1*($4 - $5)/2)
            +     	    eval(   $6/2)  eval(($4 - $5)/2) eval($5) "2" 0x100)
            +     	)
            +     
            +     	# silk screen
            +     	# ends
            +     	ElementLine(XMIN YMIN XMIN YMAX 10)
            +     	ElementLine(XMAX YMAX XMAX YMIN 10)
            +     	# sides
            +     ifelse($9,"no",
            +     	#skip side silk
            +     	,
            +     	ElementLine(XMIN YMIN XMAX YMIN 10)
            +     	ElementLine(XMAX YMAX XMIN YMAX 10)
            +     )
            +     	Mark(0 0)
            +     )')
            +
            +

            Note that the part has been defined with the mark located at +(0,0) and that the pads have been placed with the mark at the +common centroid of the footprint. While not a requirement, this is +highly desirable when developing a library that will need to interface +with a pick and place machine used for factory assembly of a board. + +

            The final part of example.inc defines particular versions of the +generic footprint we have created. These particular versions correspond +to various industry standard package sizes. +

                 # 0402 package
            +     #
            +     # 30x30 mil pad, 15 mil metal-metal spacing=>
            +     # 15 + 15 + 15 = 45 center-to-center
            +     define(`PKG_RC0402',
            +       `COMMON_PKG_RCSMT(`$1', `$2', `$3', 30, 30, 45, 0, 10, "no")')
            +     
            +     # 0603 package
            +     #
            +     # 40x40 mil pad, 30 mil metal-metal spacing=>
            +     #  30 + 20 + 20 = 70 center-to-center
            +     define(`PKG_RC0603',
            +       `COMMON_PKG_RCSMT(`$1', `$2', `$3', 40, 40, 70, 10, 10)')
            +     
            +     # 1206 package
            +     #
            +     # 40x60 mil pad, 90 mil metal-metal spacing=>
            +     #  90 + 20 + 20 = 130 center-to-center
            +     define(`PKG_RC1206',
            +       `COMMON_PKG_RCSMT(`$1', `$2', `$3', 60, 40, 130, 10, 10)')
            +
            +

            At this point, the example.inc file could be used by third party +tools such as gsch2pcb. However to fully integrate our +footprints into PCB we need to create the example.m4 and +example.list files. The example.m4 file defines +descriptions for the new footprints. +

                 define(`Description_my_RC0402',
            +       ``Standard SMT resistor/capacitor (0402)'')
            +     define(`Description_my_RC0603',
            +       ``Standard SMT resistor/capacitor (0603)'')
            +     define(`Description_my_RC1206',
            +       ``Standard SMT resistor/capacitor (1206)'')
            +
            +

            Finally we need to create the example.list file. +

                 my_RC0402:RC0402:RES0402
            +     my_RC0402:RC0402:CAP0402
            +     my_RC0603:RC0603:RES0603
            +     my_RC0603:RC0603:CAP0603
            +     my_RC1206:RC1206:RES1206
            +     my_RC1206:RC1206:CAP1206
            +
            +

            The first field in the list file has the name corresponding to the +Description definitions in example.m4. The second field is the +template name which corresponds to the macros PKG_* we defined in +example.inc with the leading PKG_ removed. It is the +second field which controls what footprint will actually appear on the +board. The final +field is the name of the part type on the board. The first line in our +example.list file will produce a menu entry in the library window +that reads: +

                 CAP0402, Standard SMT resistor/capacitor (0402)
            +
            +

            The CAP0402 portion comes directly from the third field in +example.list and the longer description comes from descriptions +macros in example.m4. Please note that any extra white space +at the end of a line in the .list files will cause them to +not work properly. + +

            9.1.4 Troubleshooting Old Style Libraries

            + +

            A powerful technique to help debug problems with libraries is to invoke +the m4 processor directly. This approach will provide error +output which is not visible from within PCB. The following example +shows how one might try to debug an 8 pin small outline (SO8) package. The +macro name for the package is PKG_SO8. In this example, the +canonical name that is to be associated with the part is SO8, the +reference designator is U1, and the value is MAX4107 (the part number). + +

                 echo "PKG_SO8(SO8, U1, MAX4107)" | \
            +        gm4 common.m4 - | \
            +        awk '/^[ \t]*$/ {next} {print}' | \
            +        more
            +
            +

            The awk call simply removes blank lines which make the output +hard to read. + +

            For this particular example, the output is: +

                 Element(0x00 "SO8" "U1" "MAX4107" 146 50 3 100 0x00)
            +     (
            +     	Pad(10 25 38 25 20 "1" 0x00)
            +     	Pad(10 75 38 75 20 "2" 0x100)
            +     	Pad(10 125 38 125 20 "3" 0x100)
            +     	Pad(10 175 38 175 20 "4" 0x100)
            +     	Pad(214 175 242 175 20 "5" 0x100)
            +     	Pad(214 125 242 125 20 "6" 0x100)
            +     	Pad(214 75 242 75 20 "7" 0x100)
            +     	Pad(214 25 242 25 20 "8" 0x100)
            +     	ElementLine(0 0 151 0 10)
            +     	ElementArc(126 0 25 25 0 180 10)
            +     	ElementLine(101 0 252 0 10)
            +     	ElementLine(252 0 252 200 10)
            +     	ElementLine(252 200 0 200 10)
            +     	ElementLine(0 200 0 0 10)
            +     	Mark(29 25)
            +     )
            +
            +

            9.2 New Style Libraries

            + +

            Footprints for the new style library are created graphically using the +PCB program. A single footprint is saved in each file. + +

            9.2.1 Creating Newlib Footprints

            + +

            To create +

              +
            1. Start PCB with an empty layout. +
            2. Make the component layer active. +
            3. For a leaded part, select the via tool and place vias where the +pads for the part should go. For surface mount pads, draw line +segments. Note that until the footprint is completed, the surface +mount pads will remain rounded. Currently a rectangle or polygon +may not be used as a pad. +
            4. For each via and line segment which will become a pad, select it +and press 'n' to be able to enter a name. Enter +the pin number and press enter. +
            5. Make the silk layer active. +
            6. Using the line and arc tools, draw a silk screen outline for the +part. +
            7. Using the selection tool, select all of the pins and silk screen +for the part. +
            8. Place the pointer above the reference point for the part. This is +typically the common centroid. Keeping the pointer there, shift-right-click +to bring up the popup menu and choose "convert +selection to element". +
            9. At this point, the vias, line segments, and silk screen will have +been converted to an element. To change any of the line segments to +have square ends rather than round ends, select the pads by holding +down the shift key and clicking each pad with the center mouse button. +Now under the Select menu, "Change square-flag of selected objects" +section, choose "Pins". +
            10. Select the element, shift-right-click to bring up the popup menu, and +choose "Copy Selection to Buffer". Now left-click on the center of +the new element. +
            11. Under the buffer menu, choose "save buffer elements to file" to +save the new footprint to a file. +
            12. Press ESC to exit from buffer mode. +
            + +

            9.2.2 Modifying Newlib Footprints

            + +
              +
            1. In the pcb-rnd program, instantiate the footprint you wish to modify. +
            2. Using the selection tool, select the footprint. +
            3. Now left-click on the selected element, this brings up a popup menu, choose +"Cut Selection to Buffer" from the popup menu. +
            4. Under the buffer menu, choose "break buffer element to pieces", +and then left-click to place the broken apart footprint to an open area of +the layout. Note that you must use the items under the buffer menu, the +items with the same names in the popup menu do not work. +
            5. Make your desired modifications to the footprint and then convert +the pieces back to an element using the same procedure as when starting +from scratch on a new footprint. +
            + + +
            + +


            +Next: , +Previous: Library Creation, +Up: Top + +
            + +

            9 Schematic Capture for PCB

            + +

            +When designing a circuit board of any complexity, a schematic capture +front-end for the design is highly desired. Any schematic capture +program which is able to generate a netlist in a user defined format as +well as a bill of materials can be made to work with PCB. Currently, we +are aware of two freely available schematic capture programs which can +interface with PCB. This chapter shows how a design can be taken from +start to finish using either of these two tools for schematic capture +and PCB for layout. + +

            + +
            + +


            +Next: , +Up: Schematic Frontends + +
            + +

            10.1 gEDA

            + +

            +This section shows how to use gEDA as the schematic capture front-end for +a PCB design. This section is not intended to be complete documentation +on gEDA and it is assumed that the user has at least some familiarity +with the gEDA suite of programs. + +

            The basic steps in a gEDA + PCB design flow are: +

              +
            1. Set up project directories +
            2. Set up gEDA (gschem/gnetlist) config files +
            3. Set up gsch2pcb config files +
            4. Capture schematics using gschem (part of gEDA) +
            5. Create any unique PCB footprints needed for the design +
            6. Generate initial PCB design using gsch2pcb (part of gEDA) +
            7. Layout circuit board using pcb +
            8. Make any additional schematic changes with gschem and +forward annotate to PCB with gsch2pcb +
            9. Generate photoplot files (RS-274X, also known as "Gerber") for +board vendor +
            + +

            10.1.1 Set Up Project Directories

            + +

            Although not required, a typical project directory will contain the +schematics and board layout at the top level. +Schematic symbols and circuit board footprints which are unique to this +project are stored in subdirectories. For this example, sym +contains the project specific schematic symbols and pkg contains +the project specific footprints. Set up the project subdirectory and +subdirectories by executing: +

                 mkdir ~/myproj
            +     cd ~/myproj
            +     mkdir sym
            +     mkdir pkg
            +     mkdir pkg/newlib
            +     mkdir pkg/m4
            +
            +

            10.1.2 Set Up gEDA Config Files

            + +

            The gEDA tools, specifically gschem and gnetlist, use +configuration files to set the search path for symbol libraries in +addition to other user preferences. Create a file in the top level +project directory called gschemrc. Add the following lines to +that file: +

                 
            +     ;; list libraries here.  Order matters as it sets the
            +     ;; search order
            +     (component-library "./sym")
            +     
            +
            +

            This sets the local search path for the schematic capture program +gschem. Now the netlister, gnetlist, must also be +configured. This can be done by copying the file gschemrc to +gnetlistrc by running ‘cp gschemrc gnetlistrc’. +Alternatively, you can create a soft link so only a single file needs to +be updated if additional symbol paths are added. The link is created by +running ‘ln -s gschemrc gnetlistrc’. + +

            10.1.3 Set Up gsch2pcb Config Files

            + +

            The program gsch2pcb, not to be confused with the older +gschem2pcb script, is used to link the schematic to layout. +gsch2pcb is responsible for creating the netlist used to provide +connectivity information to PCB as well creating an initial layout with +all components instantiated in the design. Forward annotation of +schematic changes to the layout is also done using gsch2pcb. +gsch2pcb uses a project file to set up the schematic file names, +PCB library locations, and output file names. Create a project file +called project using the following as an example: +

                 
            +     # List all the schematics to be netlisted
            +     # and laid out on the pc board.
            +     schematics      first.sch second.sch third.sch
            +     
            +     # For an output-name of foo, gsch2pcb generates files
            +     # foo.net, foo.pcb, and foo.new.pcb.  If there is no
            +     # output-name specified, the file names are derived from
            +     # the first listed schematic, i.e. first.net, etc.
            +     output-name  preamp
            +     
            +
            +

            10.1.4 Capture Schematics Using gschem

            + +

            This section is fairly brief and assumes familiarity with using the +gschem schematic capture program. As you are creating your +schematics, be sure to observe the following rules: +

              +
            • Make sure that each component in the schematic has a +footprint attribute that corresponds to a footprint in the PCB +library or a footprint you plan on creating. +
            • Make sure all reference designators are unique. One way to ensure +this is to run the refdes_renum script (part of gEDA) after the +schematics are created. +
            + +

            10.1.5 Create Any Unique PCB Footprints

            + +

            Create the new footprints you design needs using either the m4 style or +newlib style of PCB libraries. Refer to Library Creation for details on this +process. For m4 style footprints, store them in the pkg/m4 +subdirectory and for newlib footprints, store them in the +pkg/newlib subdirectory. + +

            10.1.6 Generate Initial PCB Design Using gsch2pcb

            + +

            The gsch2pcb program connects the schematic and layout. It basic +operation is to call gnetlist to generate the connectivity +netlist that PCB used to verify connectivity and to instantiate all +elements found in the schematic to a new layout. +The default, as of gsch2pcb version 0.9, is to use any found m4 +style parts first and then search for newlib style if no old style part +was found. By using the --use-files or -f flag to gsch2pcb +priority is given to newlib style parts even if m4 style are found. You +may wish to verify this in the gsch2pcb documentation in case +this changes in the future. +To start your layout, +run ‘gsch2pcb project’ where project is the project file +created previously. This will create a new netlist file, +preamp.net, and a new layout file, preamp.pcb. + +

            10.1.7 Layout Circuit Board

            + +

            Run PCB on the new layout by running ‘pcb preamp.pcb’. +Load the netlist file by selecting "load netlist file" from the "file" +menu. In the file selection dialog box, choose preamp.net. This +loads connectivity information into PCB. + +

            Using the selection tool, grab and move apart the various footprints +with the middle mouse button. Once the parts are moved apart from each +other, choose "optimize rats-nest" from the "Connects" menu. This menu +choice will display and optimize the rats nest. Use the rats nest to +help guide placement of the parts. You may wish to re-run the "optimize +rats-nest" command after moving parts around. + +

            After the placement is complete, use the line tool to add traces to the +board. As traces are added, the corresponding rats line will disappear. + +

            10.1.8 Forward Annotation of Schematic Changes

            + +

            If schematic changes are made after the layout has started, +gsch2pcb can be used to forward annotate these changes to the +layout. To forward annotate schematic changes, run ‘gsch2pcb +project’. This command will create the files preamp.new.pcb, +preamp.net, and modify the file preamp.pcb. The +modifications to preamp.pcb include forward annotation of +schematic component value changes, adds any new components, and removes +any deleted components. + +

            10.1.9 Generate Photoplot Files (RS-274X)

            + +

            After the layout is complete, choose "edit layer-groupings" from the +"Settings" menu. The LayerGroups form lets you specify which layers +will appear in each output layer group. For example, in the default +form, layer group 1 has "front" and "front side" in it. The +output file 1.gbr if DOS file names are used, or +somename_front.gbr if long file names are used will contain the +"front" and "front side" layers in it. Usually the defaults are +sufficient, but this form is still a useful reference. + +

            Choose "print layout..." from the "File" menu. In the print dialog box, +select "Gerber/RS-274X" for the device +driver. Select the "outline", "alignment", and "drillhelper" options. +To get DOS compatible file names, select the "DOS (8.3) names" option, +otherwise enter "preamp" for the filename. Press "OK". + +

            The following output files should have been created in the project directory. +The names in parentheses correspond to the DOS compatible output file names. +

            +
            preamp_frontsilk.gbr (csilk.gbr)
            Top side silk screen. +
            preamp_frontmask.gbr (cmask.gbr)
            Top side soldermask relief. +
            preamp_front.gbr (1.gbr)
            Top copper. +
            preamp_backmask.gbr (smask.gbr)
            Bottom side soldermask relief. +
            preamp_back.gbr (2.gbr)
            Bottom Copper. +
            preamp_fab.gbr (fab.gbr)
            Fabrication drawing. Also known as the drill drawing. This drawing is +used for reference by the board vendor but is not directly used in the +fabrication process. +
            preamp_plated-drill.cnc (pdrill.cnc)
            NC Drill format file for the plated through holes. +
            preamp_unplated-drill.cnc (udrill.cnc)
            NC Drill format file for the unplated through holes. +
            preamp_bom.txt (bom.txt)
            A bill of materials for the layout. +
            preamp_xy.txt (xy.txt)
            Centroid (X-Y) data for driving automated assembly equipment. +
            + + + +
            + +


            +Previous: gEDA, +Up: Schematic Frontends + +
            + +

            10.2 xcircuit

            + +

            +If anyone cares to contribute this section, it will get added. Please +submit changes to the bug tracking system for PCB which can be found from +the PCB homepage at http://pcb.gpleda.org. + + +

            + +


            +Next: , +Previous: Schematic Frontends, +Up: Top + +
            + +

            Appendix A Installation and Troubleshooting

            + +

            Compiling and installing the package should be straightforward. If any problems +occur, please contact the author Thomas.Nau@rz.uni-ulm.de, or the +current maintainer haceaton@aplcomm.jhuapl.edu to find +a solution and include it into the next release. + +

            + +
            + +


            +Next: , +Up: Installation + +
            + +

            A.1 Compiling and Installing

            + +

            +This section covers the steps which are necessary to compile the package. + +

            + +
            + +


            +Next: , +Up: compiling + +
            + +

            A.1.1 Quick Start

            + +

            +Starting with version 2.0, pcb-rnd has switched to a GNU +autoconf/automake build system. Installation of pcb-rnd consists of +three steps: configuration, building, and installing. +In a typical installation, these steps are as simple as +

                 ./configure
            +     make
            +     make install
            +
            +
            + +


            +Previous: quickstart, +Up: compiling + +
            + +

            A.1.2 Running the configure Script

            + +

            +The configure script accepts all of the standard GNU configure +options. For a complete list of configuration options, run +./configure --help. + + + +

            INFOLIBDIR
            must be set to the directory where your GNU info files are located. + +


            PCBLIBDIR
            is the path of a directory where the font files will be installed. + +


            DEFAULTFONT
            the name of the default font file. + +


            DEFAULTLIBRARY
            the name of the default library. + +


            GNUM4
            the name of GNUs m4 version. + +


            BTNMOD
            If your window manager has already bound Mod1 together with some +function keys you may want to change this setting. This is true for HP-VUE. + +
            + +

            If you find things which must be changed to compile on your system, +please add the appropriate autoconf tests (if you are familiar with +that) and mail a copy to the maintainer, harry eaton, at +haceaton@aplcomm.jhuapl.edu. + +

            If you do not have the appropriate permissions you should run +./pcbtest.sh in the src directory to run pcb-rnd from +the installation directory. + +

            + +


            +Previous: compiling, +Up: Installation + +
            + +

            A.2 Troubleshooting

            + +

            +There are some known problems. Most of them are related to +missing parts of a standard X11 distribution. Some others are caused by +third party applications such as X servers. To make this list more +complete please mail your problems and, if available, solutions to the author. +The mail address may be found at the beginning of this chapter. +In any case, read X11. + +

            By the way, you MUST HAVE AN ANSI COMPILER to make pcb-rnd work. + +

            Another source of problems are older versions of flex and bison. +pcb-rnd definitely works with flex-2.4.7 and bison-1.22 or +later. The problems will result in a syntax error while parsing files. +This should only be a problem if you have modified the flex or +bison input files. + +

            The following list gives you just an idea because I'm not able to test +all pcb-rnd releases on all platforms. + +

            + +
            + +


            +Next: , +Up: problems + +
            + +

            A.2.1 HP Series 700 and 800

            + +

            +You have to install several X11 include files +or, better, install a complete X11R5 release. Hewlett-Packard doesn't +support the Athena Widgets. So the header files and libraries are missing +from the application media, but they are available as a patch. +They also do not ship the ANSI compiler with the normal operating +system release so you have to buy one or use GCC. +Some of the tools are available as patches. + +

            In addition, pcb-rnd has been successfully tested on these platforms with +HPUX 9.*, 10.* running self-compiled X11R5. + +

            + +


            +Next: , +Previous: HP, +Up: problems + +
            + +

            A.2.2 Sun SPARC architecture

            + +

            +There are no known problems with Sun machines if they use X11R5 instead +of OpenWindows. pcb-rnd compiled successfully with all kinds of +SPARCstations Solaris-2.[345]. + +

            For problems with OpenWindows refer to X11. + +

            + +


            +Next: , +Previous: Sun, +Up: problems + +
            + +

            A.2.3 Silicon Graphics

            + +

            +pcb-rnd has been tested on some boxes running either IRIX-4.0.5 or +IRIX-5.3. The former one uses a X11R4 server. +There are no problems. +For known problems +with X11R4, see X11. + +

            + +


            +Next: , +Previous: SGI, +Up: problems + +
            + +

            A.2.4 DEC Alpha

            + +

            +pcb-rnd compiled and runs without problems on DEC UNIX V3.2c. + +

            + +


            +Next: , +Previous: DEC Alpha, +Up: problems + +
            + +

            A.2.5 SCO Unix

            + +

            +John DuBois <spcecdt@deeptht.armory.com> wrote: +

                 SCO-ODT-3.0 requires the latest version of tls003, the Athena
            +     widget library (available from sosco.sco.com). The main problems
            +     I have encountered are it core dumps fairly often, especially
            +     while loading/dropping elements...
            +
            +

            I'll see what I am able to do as soon as I have access to an SCO system. + +

            + +


            +Next: , +Previous: SCO, +Up: problems + +
            + +

            A.2.6 Linux

            + +

            +Since the X11 version of pcb-rnd has been developed on a Linux +system here are no known problems. + +

            + +


            +Next: , +Previous: Linux, +Up: problems + +
            + +

            A.2.7 FreeBSD and NetBSD

            + +

            +pcb-rnd has been tested on NetBSD and works without any problems. +You may also be able to find a NetBSD package at +ftp://ftp.netbsd.org/pub/NetBSD/packages/cad/pcb/README.html or a +FreeBSD port at +http://www.freebsd.org/cgi/url.cgi?ports/cad/pcb/pkg-descr. + +

            + +


            +Next: , +Previous: BSD, +Up: problems + +
            + +

            A.2.8 Problems related to X11

            + +

            +There are a some problems related to X11R4 or systems derived from +X11 such as OpenWindows. See Sun. You at least have to change +all occurances of baseTranslations in the resource files to +translations if you are using a X11R4 server. Look at the +X11R5 Intrinsics manual for details. + +

            The panner widget (print dialog box) appears only in release X11R5 and +later. It really simplifies adjusting the offsets. +With earlier releases the printout will always appear in the center of the +page. + +

            You may have some problems in a mixed X11-OpenWindows +environment. + +

            pcb-rnd has been tested successfully with X11R6 under Linux 1.1.59 +and later. + +

            + +


            +Previous: X11, +Up: problems + +
            + +

            A.2.9 Problems related to TeX

            + +

            +If your TeX installation complains about a missing texinfo.tex +file copy the one included in this release (directory doc +to your TeX macro directory. +Note, there are probably newer versions of this file available from some +FTP sites. +TeX-3.0 failed, TeX-3.14 worked just fine. Check our FTP server +ftp.uni-ulm.de for ready-to-print versions of the manuals. + + +

            + +


            +Next: , +Previous: Installation, +Up: Top + +
            + +

            Appendix B Customizing the Menus

            + +

            The menu system is driven off a data file that contains +resources. A resource is a hierarchical description of a data +tree which, in this case, is mapped to the hierarchical menus used by +pcb-rnd. + +

            + +
            + +


            +Next: , +Up: Custom Menus + +
            + +

            B.1 Resource Syntax

            + +

            A resource file is a simple text file. It contains curly braces to +group things, spaces between things, and double quotes when strings +need to include spaces. There are four fundamental ways of adding +data to a resource. + +

            First, a string (either a single word or a quoted string with spaces, +we call both “strings” in this appendix) can be added all by itself, +to add a string resource to the current resource. This is used, for +example, to define the string printed on a menu button. In this +example, four strings are added to the File resource: + +

                 File = {
            +       Sample
            +       "longer sample"
            +       some text
            +     }
            +
            +

            Second, a named string may be added by giving two strings separated by +an equals sign. This is used to specify X resources and a few other +optional parameters of menus, for example. Note that a string all by +itself is thus an “unnamed” string. + +

                 {"Layer groups" foreground=red sensitive=false}
            +
            +

            Third, an unnamed subresource may be added. This is used to create +submenus and menu buttons. To add a subresource, simply group other +things in curly braces. This example describes a resource containing +one string and three subresources: + +

                 {File
            +       {New do_new()}
            +       {Save do_save()}
            +       {Quit do_quit()}
            +     }
            +
            +

            Lastly, a named subresource may be added by prefixing an unnamed +subresource with a string and an equals sign, just as when naming +strings. This syntax is used to name the resources used for the main +menu and popup menus: + +

                 MainMenu = {
            +       ...
            +       }
            +
            +

            Additionally, the menu parser allows for “hooks” whereby portions of +the menu system can be programmatically created at runtime by the +application. These hooks are invoked by a single word proceeded by an +at sign, such as this example where most of the Sizes menu is created +automatically: + +

                 {Sizes
            +         @sizes
            +         {"Adjust active sizes ..." AdjustStyle(0)}
            +         }
            +
            +

            In addition to all that, any unquoted pound sign (#) begins a +comment. Commented text continues until the end of the containing +line. Comments may begin at the beginning of a line, or after other +text on the line: + +

                 # This is a comment
            +     MainMenu = { # This is also a comment
            +
            +
            + +


            +Next: , +Previous: Resource Syntax, +Up: Custom Menus + +
            + +

            B.2 Menu Definitions

            + +

            To best understand this section, you should find the +pcb-menu.res file that your pcb-rnd uses and refer to it for +examples (see Menu Files and Defaults). Note that the lesstif +GUI uses pcb-menu.res and the GTK+ GUI uses gpcb-menu.res. +The file format is identical however and if so desired, one can make +one file be a soft link to the other. + +

            A resource defines a menu when it meets certain semantic requirements. +The menu hierarchy is reflected as a hierarchy of unnamed +subresources, with the first string of each subresource defining the +label used for the menu button. A subresource that itself contains +subresources becomes a submenu, a subresource that does not becomes a +button. + +

            A submenu should only contain subresources for the buttons or submenus +within that submenu. Two exceptions are allowed: an initial string +sets the label, and the string “-” (a single dash) will create a +separator. + +

            A button should not contain subresources, but will contain many +strings, named and unnamed. The first member shall be an unnamed +string which is the label for the button. Any other unnamed strings +within the button's resource will be used as actions (much like the +.Xdefaults action strings), which are functions that will be called +when the button is pressed (or popped up, or created, depending on the +action). As a convenience, if a left parenthesis is seen, the current +“word” will continue at least until the matching right parenthesis. +This allows you to pass strings with spaces as arguments to actions +without needing to quote the action. + +

            Named resources in button resources will be used as X resources. Such +resources can be used to set the font, color, and spacing of buttons. +As a convenience, “fg” can be used as an abbreviation for “foreground”. + +

            Within the menu's resource file, pcb-rnd will look for a few key named +subresources. At the moment, the only one it looks for is one called +MainMenu. This will be used for the main menu bar. In the +future, other named subresources will be used for popup resources. + +

            Given all this, a small sample pcb-menu.res would be: + +

                 MainMenu = {
            +       {File
            +         {"Load layout" Load(Layout)}
            +         -
            +         {"Quit Program" Quit() fg=red font=10x20}
            +       }
            +     }
            +
            +

            Within the pcb-rnd sources are specially crafted comments that mark all +the actions, flags, menu hooks, and whatnot that pcb-rnd offers. Read the +file src/gather-actions in the pcb-rnd source tree for +documentation for these comments. + +

            + +


            +Previous: Menu Definitions, +Up: Custom Menus + +
            + +

            B.3 Menu Files and Defaults

            + +

            pcb-rnd will look for a file which defines its menus, trying the following +names (the example is for the lesstif GUI, the GTK+ GUI has “gpcb-menu.res” +in place of “pcb-menu.res”): + +

                 ./pcb-menu.res
            +     $HOME/.pcb-menu.res
            +     $PCBLIBDIR/pcb-menu.res
            +     <internal>
            +
            +

            Note that pcblibdir defaults to /usr/local/share/pcb +(hence, /usr/local/share/pcb/pcb-menu.res). The +<internal> entry refers to a menu definition within the pcb-rnd +application itself. The master file for all this is the file +src/pcb-menu.res in the pcb-rnd source tree. This master source is +used to create the internal menu definition as well as being installed +in $pcblibdir. + + +

            + +


            +Next: , +Previous: Custom Menus, +Up: Top + +
            + +

            Appendix C Element Search/Regular Expressions

            + +

            + +

            C.1 Element Search/Regular Expressions

            + +

            pcb-rnd's search is based on POSIX 1003.2 Regular Expressions. Full POSIX +Regular Expressions are supported by pcb-rnd if the regex library was +available when pcb-rnd was built. One difference from the regular +expressions found in tools like awk or grep is that PCB implicitly +adds a “^” to the begining of a regular expression and “$” to the +end of the regular expression. For example, if you enter “C1”, the +actual regular expression used internally is “^C1$”. Another difference +is that search patterns in pcb are not case sensitive. That is, “CON” is +treated the same as “con”. + +

            It is easier to show by example how to search than explain +POSIX 1003.2. With regular expressions most characters are just +themselves, but some are special: + +

            +
            *
            Matches 0 or more instances of preceding character. + +
            +
            Matches 1 or more instances of preceding character. + +
            ?
            Matches 0 or 1 instances of preceding character. + +
            .
            Matches any single character other than the newline character. + +
            |
            The vertical bar is the alternation operator. It combines two +regular expressions. The result matches if either of them matches. + +
            \
            A backslash indicates the next character should not be interpreted literally +if it normally is, and should be interpreted literally if it normally isn't. + +
            {n}
            An integer n enclosed in curly brackets matches the preceding item if +it occurs exactly n times. + +
            [ ]
            A pair of square brackets matches every character they contain. Characters +may be given explicitly, or as ranges. + +
            -
            A hyphen in the context of square brackets denotes the range between the +preceding and the following character. E.g., the range of digits is +“0-9” . The range of letters from C to K is “C-K” . + +
            \^ inside square brackets
            Inside square brackets the caret is an anti operator. Its presence makes +the square prackets match anything except the contents of the brackets. + +
            ( )
            Round parenthesis group parts of a regular expression. This is very much +like they do in math formulars. + +
            + +

            If you need a special character literally, you can escape it with a +backslash. + +

            The following examples illustrate how regular expressions can be used to +specify element names (reference designators) to search for. +

            +
            C5
            Select the element whose name is exactly “C5”. + +
            C5 | R3
            Select C5 and R3. + +
            C.*
            Select all elements whose name start with the letter “C”, such as C5, or +C42, or CF1. + +
            C.*1
            Select all elements that start with “C” and end with “1”, such as C1, +or C51 or C5/9B71. + +
            R10?
            Search for R1 or R10, but will not select R100 or R105. The question mark +is a quantifier for the character “0”. + +
            R128+
            Selects R128, R1288, R12888, etc. + +
            TB.
            Select all terminal blocks having exactly one character designator after +“TB” such as TB1, TBA, or TBx but not TB. + +
            TB..
            Select all terminal blocks having a two character designator such as TB21 or +TB1a. + +
            TB.*
            Select all terminal blocks with any designator. + +
            .*31
            Select all items, whose name ends with “31” such as Q31, or R31, or R531. + +
            Q[12]
            Select Q1 and Q2. + +
            [A-D].*
            Select all items, whose name starts with “A”, “B”, “C”, or “D”. + +
            .*N{2}.*
            Select all items, whose name contains two “N” in a row such as +CONN23, or connA, but not CON5 + +
            [^D].*
            Select all items that do not start with the letter “D”, such as C2, or +R34, but not D34 + +
            + + +
            + +


            +Next: , +Previous: Regular Expressions, +Up: Top + +
            + +

            Appendix D Standard Drill Size Tables

            + +

            + +

            D.1 American Standard Wire Size Drills

            + + + +

            Drill Diameter Drill Diameter Drill Diameter +
            Size (inches) Size (inches) Size (inches) + +


            97 .0059 96 .0063 95 .0067 +
            94 .0071 93 .0075 92 .0079 +
            91 .0083 90 .0087 89 .0091 +
            88 .0095 87 .0100 86 .0105 +
            85 .0110 84 .0115 83 .0120 +
            82 .0125 81 .0130 80 .0135 +
            79 .0145 78 .0160 77 .0180 +
            76 .0200 75 .0210 74 .0225 +
            73 .0240 72 .0250 71 .0260 +
            70 .0280 69 .0292 68 .0310 +
            67 .0320 66 .0330 65 .0350 +
            64 .0360 63 .0370 62 .0380 +
            61 .0390 60 .0400 59 .0410 +
            58 .0420 57 .0430 56 .0465 +
            55 .0520 54 .0550 53 .0595 +
            52 .0635 51 .0670 50 .0700 +
            49 .0730 48 .0760 47 .0785 +
            46 .0810 45 .0820 44 .0860 +
            43 .0890 42 .0935 41 .0960 +
            40 .0980 39 .0995 38 .1015 +
            37 .1040 36 .1065 35 .1100 +
            34 .1110 33 .1130 32 .1160 +
            31 .1200 30 .1285 29 .1360 +
            28 .1405 27 .1440 26 .1470 +
            25 .1495 24 .1520 23 .1540 +
            22 .1570 21 .1590 20 .1610 +
            19 .1660 18 .1695 17 .1730 +
            16 .1770 15 .1800 14 .1820 +
            13 .1850 12 .1890 11 .1910 +
            10 .1935 9 .1960 8 .1990 +
            7 .2010 6 .2040 5 .2055 +
            4 .2090 3 .2130 2 .2210 +
            1 .2280 +
            + +

            D.2 American Standard Letter Size Drills

            + + + +

            Drill Diameter Drill Diameter Drill Diameter +
            Size (inches) Size (inches) Size (inches) + +


            A .2340 B .2380 C .2420 +
            D .2460 E .2500 F .2570 +
            G .2610 H .2660 I .2720 +
            J .2770 K .2810 L .2900 +
            M .2950 N .3020 O .3160 +
            P .3230 Q .3320 R .3390 +
            S .3480 T .3580 U .3680 +
            V .3770 W .3860 X .3970 +
            Y .4040 Z .4130 +
            + +

            D.3 Fractional Inch Size Drills

            + + + +

            Drill Diameter Drill Diameter Drill Diameter +
            Size (inches) Size (inches) Size (inches) + +


            1/64 .0156 1/32 .0313 3/64 .0469 +
            1/16 .0625 5/64 .0781 3/32 .0938 +
            7/64 .1094 1/8 .1250 9/64 .1406 +
            5/32 .1562 11/64 .1719 3/16 .1875 +
            13/64 .2031 7/32 .2188 15/64 .2344 +
            1/4 .2500 17/64 .2656 9/32 .2812 +
            19/64 .2969 5/16 .3125 21/64 .3281 +
            11/32 .3438 23/64 .3594 3/8 .3750 +
            25/64 .3906 13/32 .4062 27/64 .4219 +
            7/16 .4375 29/64 .4531 15/32 .4688 +
            31/64 .4844 1/2 .5000 33/64 .5156 +
            17/32 .5313 35/64 .5469 9/16 .5625 +
            37/64 .5781 19/32 .5938 39/64 .6094 +
            5/8 .6250 41/64 .6406 21/32 .6562 +
            43/64 .6719 11/16 .6875 45/64 .7031 +
            23/32 .7188 47/64 .7344 3/4 .7500 +
            49/64 .7656 25/32 .7812 51/64 .7969 +
            13/16 .8125 53/64 .8281 27/32 .8438 +
            55/64 .8594 7/8 .8750 57/64 .8906 +
            29/32 .9062 59/64 .9219 15/16 .9375 +
            61/64 .9531 31/32 .9688 63/64 .9844 +
            1 1.0000 +
            + +

            D.4 Metric Drills

            + + + +

            Drill Diameter Drill Diameter Drill Diameter +
            Size (inches) Size (inches) Size (inches) + +


            0.20 mm .00787 0.25 mm .00984 0.30 mm .0118 +
            0.35 mm .0138 0.40 mm .0158 0.45 mm .0177 +
            0.50 mm .0197 0.55 mm .0217 0.60 mm .0236 +
            0.65 mm .0256 0.70 mm .0276 0.75 mm .0295 +
            0.80 mm .0315 0.85 mm .0335 0.90 mm .0354 +
            0.95 mm .0374 1.00 mm .0394 1.05 mm .0413 +
            1.10 mm .0433 1.15 mm .0453 1.20 mm .0472 +
            1.25 mm .0492 1.30 mm .0512 1.35 mm .0531 +
            1.40 mm .0551 1.45 mm .0571 1.50 mm .0591 +
            1.55 mm .0610 1.60 mm .0630 1.65 mm .0650 +
            1.70 mm .0669 1.75 mm .0689 1.80 mm .0709 +
            1.85 mm .0728 1.90 mm .0748 1.95 mm .0768 +
            2.00 mm .0787 2.05 mm .0807 2.10 mm .0827 +
            2.15 mm .0846 2.20 mm .0866 2.25 mm .0886 +
            2.30 mm .0906 2.35 mm .0925 2.40 mm .0945 +
            2.45 mm .0965 2.50 mm .0984 2.55 mm .1004 +
            2.60 mm .1024 2.65 mm .1043 2.70 mm .1063 +
            2.75 mm .1083 2.80 mm .1102 2.85 mm .1122 +
            2.90 mm .1142 2.95 mm .1161 3.00 mm .1181 +
            3.10 mm .1220 3.15 mm .1240 3.20 mm .1260 +
            3.25 mm .1280 3.30 mm .1299 3.40 mm .1339 +
            3.50 mm .1378 3.60 mm .1417 3.70 mm .1457 +
            3.75 mm .1476 3.80 mm .1496 3.90 mm .1535 +
            4.00 mm .1575 4.10 mm .1614 4.20 mm .1654 +
            4.25 mm .1673 4.30 mm .1693 4.40 mm .1732 +
            4.50 mm .1772 4.60 mm .1811 4.70 mm .1850 +
            4.75 mm .1870 4.80 mm .1890 4.90 mm .1929 +
            5.00 mm .1969 5.10 mm .2008 5.20 mm .2047 +
            5.25 mm .2067 5.30 mm .2087 5.40 mm .2126 +
            5.50 mm .2165 5.60 mm .2205 5.70 mm .2244 +
            5.75 mm .2264 5.80 mm .2283 5.90 mm .2323 +
            6.00 mm .2362 6.10 mm .2402 6.20 mm .2441 +
            6.25 mm .2461 6.30 mm .2480 6.40 mm .2520 +
            6.50 mm .2559 6.60 mm .2598 6.70 mm .2638 +
            6.75 mm .2657 6.80 mm .2677 6.90 mm .2717 +
            7.00 mm .2756 7.10 mm .2795 7.20 mm .2835 +
            7.25 mm .2854 7.30 mm .2874 7.40 mm .2914 +
            7.50 mm .2953 7.60 mm .2992 7.70 mm .3031 +
            8.00 mm .3150 8.10 mm .3189 8.20 mm .3228 +
            8.25 mm .3248 8.30 mm .3268 8.40 mm .3307 +
            8.50 mm .3346 8.60 mm .3386 8.70 mm .3425 +
            8.75 mm .3445 8.80 mm .3465 8.90 mm .3504 +
            9.00 mm .3543 9.10 mm .3583 9.20 mm .3622 +
            9.25 mm .3642 9.30 mm .3661 9.40 mm .3701 +
            9.50 mm .3740 9.60 mm .3780 9.70 mm .3819 +
            9.75 mm .3839 9.80 mm .3858 9.90 mm .3898 +
            10.00 mm .3937 10.10 mm .3976 10.20 mm .4016 +
            10.25 mm .4035 10.30 mm .4055 10.40 mm .4094 +
            10.50 mm .4134 10.60 mm .4173 10.70 mm .4213 +
            10.80 mm .4252 10.90 mm .4291 11.00 mm .4331 +
            11.10 mm .4370 11.20 mm .4409 11.25 mm .4429 +
            11.30 mm .4449 11.40 mm .4488 11.50 mm .4528 +
            11.60 mm .4567 11.70 mm .4606 11.75 mm .4626 +
            11.80 mm .4646 11.90 mm .4685 12.00 mm .4724 +
            12.50 mm .4921 13.00 mm .5118 13.50 mm .5315 +
            14.00 mm .5512 14.50 mm .5709 15.00 mm .5906 +
            15.50 mm .6102 16.00 mm .6299 16.50 mm .6496 +
            17.00 mm .6693 17.50 mm .6890 18.00 mm .7087 +
            18.50 mm .7283 19.00 mm .7480 19.50 mm .7677 +
            20.00 mm .7874 20.50 mm .8071 21.00 mm .8268 +
            21.50 mm .8465 22.00 mm .8661 22.50 mm .8858 +
            23.00 mm .9055 23.50 mm .9252 24.00 mm .9449 +
            24.50 mm .9646 25.00 mm .9843 +
            + + +

            + +


            +Next: , +Previous: Standard Drill Sizes, +Up: Top + +
            + +

            Appendix E Centroid (X-Y) File Format

            + +

            + +

            E.1 Overview

            + +

            E.2 File Format

            + +

            The centroid output file is in a standard comma seperated values (CSV) +format. Comment lines begin with a “#”. The output file contains a +header with an RCS Id tag (useful for those who will check the file +into a version control system), a version number for the file format, +some comments containing the author and title of the board, and a +comment describing the remainder of the file format. + +

            An example centroid file is shown below. + +

                 
            +     # $Id$
            +     # PcbXY Version 1.0
            +     # Date: Fri Jul 22 03:40:08 2005 UTC
            +     # Author: PCB User
            +     # Title: MyBoard - PCB X-Y
            +     # RefDes, Description, Value, X, Y, rotation, top/bottom
            +     # X,Y in mils.  rotation in degrees.
            +     # --------------------------------------------
            +     R61,"0603","10",2610.00,3560.00,90,top
            +     J5,"AMPHENOL_ARFX1231","unknown",2390.00,4220.00,180,top
            +     C13,"0402","0.01u",2340.00,3014.00,270,top
            +     
            +
            +

            E.3 Computation of Centroid and Rotation

            + +

            The center of each element is found by averaging the (X,Y) coordinates +for the center of each pin and pad in the element. For example if an +element has 2 pins, 1 at (1,0) and another at (1,4) then the centroid +will be at (1,2). + +

            The calculation of rotation is a bit more complex. Currently a +rotation is not stored for each element but rather the rotated element +is stored. In other words if the element from the library has a pin +at (0,0) and (0,2) and it has been rotated by 90 degrees, then the +.pcb file will store (0,0) and (2,0) for the pin locations with +no indication that they have been rotated from the original. + +

            In the event that the element has only 1 pin, then the rotation is set +to zero. If the element has only one pad (as opposed to a +through-hole pin), then the rotation of the pad is used. + +

            When the element has multiple pins, the location of pin #1 is placed +in the coordinate system which has the centroid of the part at (0,0). +Then which quadrant pin #1 falls in determines the rotation. Zero +degrees of rotation is defined as pin #1 being in the upper left +quadrant. Increasing angles correspond to counterclockwise rotation so a +rotation of 90 degrees places pin #1 in the lower left quadrant. +Currently, the only allowed rotations are 0, 90, 180, and 270 degrees. + +

            If pin #1 happens to be at the centroid of the part, then pin #2 is +examined to see which quadrant it is located in. The same rules apply +for the definitions of rotation. In other words, when pin #1 is at +the centroid of the part and pin #2 is in the upper left quadrant, the +rotation is declared to be zero degrees. + + +

            + +


            +Next: , +Previous: Centroid File Format, +Up: Top + +
            + +

            Appendix F Action Reference

            + +

            + + + +

            Many actions take a delta parameter as the last parameter, +which is an amount to change something. That delta may include +units, as an additional parameter, such as Action(Object,5,mm). +If no units are specified, the default is PCB's native units +(currently 1/100 mil). Also, if the delta is prefixed by + or +-, the size is increased or decreased by that amount. +Otherwise, the size size is set to the given amount. + +

                 Action(Object,5,mil)
            +     Action(Object,+0.5,mm)
            +     Action(Object,-1)
            +
            +

            Actions which take a delta parameter which do not accept all +these options will specify what they do take. + + + + +

            Many actions act on indicated objects on the board. They will have +parameters like ToggleObject or SelectedVias to indicate +what group of objects they act on. Unless otherwise specified, these +parameters are defined as follows: + +

            +
            Object
            ToggleObject
            Affects the object under the mouse pointer. If this action is invoked +from a menu or script, the user will be prompted to click on an +object, which is then the object affected. + +
            Selected
            SelectedObjects
            +Affects all objects which are currently selected. At least, all +selected objects for which the given action makes sense. + +
            SelectedPins
            SelectedVias
            SelectedType
            etc
            Affects all objects which are both selected and of the Type specified. + +
            + + + +
            + +


            +Next: , +Up: Action Reference + +
            + +

            F.1 Core actions

            + + +
            + +


            +Next: , +Up: core actions + +
            + +

            F.1.1 AddRats

            + + +

            +
            AddRats(AllRats|SelectedRats|Close)
            +
            + +

            Add one or more rat lines to the board. + + +

            +
            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. + +
            Close
            Selects the shortest unselected rat on the board. + +
            + +
            + +


            +Next: , +Previous: AddRats Action, +Up: core actions + +
            + +

            F.1.2 ApplyVendor

            + + +

            +
            ApplyVendor()
            +
            + +

            Applies the currently loaded vendor drill table to the current design. + + +This will modify all of your drill holes to match the list of allowed +sizes for your vendor. + +

            + +


            +Next: , +Previous: ApplyVendor Action, +Up: core actions + +
            + +

            F.1.3 Atomic

            + + +

            +
            Atomic(Save|Restore|Close|Block)
            +
            + +

            Save or restore the undo serial number. + + +

            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. + +

            +
            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. + +
            + +
            + +


            +Next: , +Previous: Atomic Action, +Up: core actions + +
            + +

            F.1.4 Attributes

            + + +

            +
            Attributes(Layout|Layer|Element)
            +Attributes(Layer,layername)
            +
            + +

            Let the user edit the attributes of the layout, current or given +layer, or selected element. + + +

            This just pops up a dialog letting the user edit the attributes of the +pcb, an element, or a layer. + +

            + +


            +Next: , +Previous: Attributes Action, +Up: core actions + +
            + +

            F.1.5 AutoPlaceSelected

            + + +

            +
            AutoPlaceSelected()
            +
            + +

            Auto-place selected components. + + +

            Attempts to re-arrange the selected components such that the nets +connecting them are minimized. Note that you cannot undo this. + +

            + +


            +Next: , +Previous: AutoPlaceSelected Action, +Up: core actions + +
            + +

            F.1.6 AutoRoute

            + + +

            +
            AutoRoute(AllRats|SelectedRats)
            +
            + +

            Auto-route some or all rat lines. + + +

            +
            AllRats
            Attempt to autoroute all rats. + +
            SelectedRats
            Attempt to autoroute the selected rats. + +
            + +

            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 line and via +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. + +

            + +


            +Next: , +Previous: AutoRoute Action, +Up: core actions + +
            + +

            F.1.7 ChangeClearSize

            + + +

            +
            ChangeClearSize(Object, delta)
            +ChangeClearSize(SelectedPins|SelectedPads|SelectedVias, delta)
            +ChangeClearSize(SelectedLines|SelectedArcs, delta
            +ChangeClearSize(Selected|SelectedObjects, delta)
            +
            + +

            Changes the clearance size of objects. + + +

            If the solder mask is currently showing, this action changes the +solder mask clearance. If the mask is not showing, this action +changes the polygon clearance. + +

            + +


            +Next: , +Previous: ChangeClearSize Action, +Up: core actions + +
            + +

            F.1.8 ChangeDrillSize

            + + +

            +
            ChangeDrillSize(Object, delta)
            +ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta)
            +
            + +

            Changes the drilling hole size of objects. + + +

            + +


            +Next: , +Previous: ChangeDrillSize Action, +Up: core actions + +
            + +

            F.1.9 ChangeFlag

            + + +

            +
            ChangeFlag(Object|Selected|SelectedObjects, flag, value)
            +ChangeFlag(SelectedLines|SelectedPins|SelectedVias, flag, value)
            +ChangeFlag(SelectedPads|SelectedTexts|SelectedNames, flag, value)
            +ChangeFlag(SelectedElements, flag, value)
            +flag = square | octagon | thermal | join
            +value = 0 | 1
            +
            + +

            Sets or clears flags on objects. + + +

            Toggles the given flag on the indicated object(s). The flag may be +one of the flags listed above (square, octagon, 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. + +

            + +


            +Next: , +Previous: ChangeFlag Action, +Up: core actions + +
            + +

            F.1.10 ChangeHole

            + + +

            +
            ChangeHole(ToggleObject|Object|SelectedVias|Selected)
            +
            + +

            Changes the hole flag of objects. + + +

            The "hole flag" of a via determines whether the via is a +plated-through hole (not set), or an unplated hole (set). + +

            + +


            +Next: , +Previous: ChangeHole Action, +Up: core actions + +
            + +

            F.1.11 ChangeJoin

            + + +

            +
            ChangeJoin(ToggleObject|SelectedLines|SelectedArcs|Selected)
            +
            + +

            Changes the join (clearance through polygons) of objects. + + +

            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. + +

            + +


            +Next: , +Previous: ChangeJoin Action, +Up: core actions + +
            + +

            F.1.12 ChangeName

            + + +

            +
            ChangeName(Object)
            +ChangeName(Layout|Layer)
            +
            + +

            Sets the name of objects. + + +

            +
            Object
            Changes the name of the element 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. + +
            + +
            + +


            +Next: , +Previous: ChangeName Action, +Up: core actions + +
            + +

            F.1.13 ChangeOctagon

            + + +

            +
            ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)
            +ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)
            +
            + +

            Changes the octagon-flag of pins and vias. + + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: ChangeOctagon Action, +Up: core actions + +
            + +

            F.1.14 ChangePaste

            + + +

            +
            ChangePaste(ToggleObject|Object|SelectedPads|Selected)
            +
            + +

            Changes the no paste flag of objects. + + +

            The "no paste flag" of a pad determines whether the solderpaste + stencil will have an opening for the pad (no set) or if there wil be + no solderpaste on the pad (set). This is used for things such as + fiducial pads. + +

            + +


            +Next: , +Previous: ChangePaste Action, +Up: core actions + +
            + +

            F.1.15 ChangePinName

            + + +

            +
            ChangePinName(ElementName,PinNumber,PinName)
            +
            + +

            Sets the name of a specific pin on a specific element. + + +

            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)
            +
            +
            + +


            +Next: , +Previous: ChangePinName Action, +Up: core actions + +
            + +

            F.1.16 ChangeSize

            + + +

            +
            ChangeSize(Object, delta)
            +ChangeSize(SelectedObjects|Selected, delta)
            +ChangeSize(SelectedLines|SelectedPins|SelectedVias, delta)
            +ChangeSize(SelectedPads|SelectedTexts|SelectedNames, delta)
            +ChangeSize(SelectedElements, delta)
            +
            + +

            Changes the size of objects. + + +

            For lines and arcs, this changes the width. For pins and vias, this +changes the overall diameter of the copper annulus. For pads, this +changes the width and, indirectly, the length. For texts and names, +this changes the scaling factor. For elements, this changes the width +of the silk layer lines and arcs for this element. + +

            + +


            +Next: , +Previous: ChangeSize Action, +Up: core actions + +
            + +

            F.1.17 ChangeSquare

            + + +

            +
            ChangeSquare(ToggleObject)
            +ChangeSquare(SelectedElements|SelectedPins)
            +ChangeSquare(Selected|SelectedObjects)
            +
            + +

            Changes the square flag of pins and pads. + + +

            Note that Pins means both pins and pads. + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: ChangeSquare Action, +Up: core actions + +
            + +

            F.1.18 ClearOctagon

            + + +

            +
            ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)
            +ClearOctagon(SelectedElements|SelectedPins|SelectedVias)
            +
            + +

            Clears the octagon-flag of pins and vias. + + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: ClearOctagon Action, +Up: core actions + +
            + +

            F.1.19 ClearSquare

            + + +

            +
            ClearSquare(ToggleObject|SelectedElements|SelectedPins)
            +
            + +

            Clears the square-flag of pins and pads. + + +

            Note that Pins means pins and pads. + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: ClearSquare Action, +Up: core actions + +
            + +

            F.1.20 ClrFlag

            + + +

            +
            ClrFlag(Object|Selected|SelectedObjects, flag)
            +ClrFlag(SelectedLines|SelectedPins|SelectedVias, flag)
            +ClrFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
            +ClrFlag(SelectedElements, flag)
            +flag = square | octagon | thermal | join
            +
            + +

            Clears flags on objects. + + +

            Turns the given flag off, regardless of its previous setting. See +ChangeFlag. + +

                 ClrFlag(SelectedLines,join)
            +
            +
            + +


            +Next: , +Previous: ClrFlag Action, +Up: core actions + +
            + +

            F.1.21 Connection

            + + +

            +
            Connection(Find|ResetLinesAndPolygons|ResetPinsAndVias|Reset)
            +
            + +

            Searches connections of the object at the cursor position. + + +

            Connections found with this action will be highlighted in the +“connected-color” color and will have the “found” flag set. + +

            +
            Find
            The net under the cursor is “found”. + +
            ResetLinesAndPolygons
            Any “found” lines and polygons are marked “not found”. + +
            ResetPinsAndVias
            Any “found” pins and vias are marked “not found”. + +
            Reset
            All “found” objects are marked “not found”. + +
            + +
            + +


            +Next: , +Previous: Connection Action, +Up: core actions + +
            + +

            F.1.22 Delete

            + + +

            +
            Delete(Object|Selected)
            +Delete(AllRats|SelectedRats)
            +
            + +

            Delete stuff. + + +

            + +


            +Next: , +Previous: Delete Action, +Up: core actions + +
            + +

            F.1.23 DeleteRats

            + + +

            +
            DeleteRats(AllRats|Selected|SelectedRats)
            +
            + +

            Delete rat lines. + + +

            + +


            +Next: , +Previous: DeleteRats Action, +Up: core actions + +
            + +

            F.1.24 DisableVendor

            + + +

            +
            DisableVendor()
            +
            + +

            Disables automatic drill size mapping. + + +

            +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. + +

            + +


            +Next: , +Previous: DisableVendor Action, +Up: core actions + +
            + +

            F.1.25 DisperseElements

            + + +

            +
            DisperseElements(All|Selected)
            +
            + +

            Disperses elements. + + +

            Normally this is used when starting a board, by selecting all elements +and then dispersing them. This scatters the elements around the board +so that you can pick individual ones, rather than have all the +elements at the same 0,0 coordinate and thus impossible to choose +from. + +

            + +


            +Next: , +Previous: DisperseElements Action, +Up: core actions + +
            + +

            F.1.26 Display

            + + +

            +
            Display(NameOnPCB|Description|Value)
            +Display(Grid|Redraw)
            +Display(CycleClip|CycleCrosshair|Toggle45Degree|ToggleStartDirection)
            +Display(ToggleGrid|ToggleRubberBandMode|ToggleUniqueNames)
            +Display(ToggleMask|ToggleName|ToggleClearLine|ToggleFullPoly|ToggleSnapPin)
            +Display(ToggleThindraw|ToggleThindrawPoly|ToggleOrthoMove|ToggleLocalRef)
            +Display(ToggleCheckPlanes|ToggleShowDRC|ToggleAutoDRC)
            +Display(ToggleLiveRoute|LockNames|OnlyNames)
            +Display(Pinout|PinOrPadName)
            +
            + +

            Several display-related actions. + + +

            +
            NameOnPCB
            Description
            Value
            Specify whether all elements show their name, description, or value. + +
            Redraw
            Redraw the whole board. + +
            Toggle45Degree
            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. + +
            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 an element 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. + +
            ToggleMask
            Turns the solder mask on or off. + +
            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 mouse pointer +is (not where the crosshair currently 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 element indicated by the cursor to be +displayed, usually in a separate window. + +
            PinOrPadName
            Toggles whether the names of pins, pads, or (yes) vias will be +displayed. If the cursor is over an element, all of its pins and pads +are affected. + +
            + +
            + +


            +Next: , +Previous: Display Action, +Up: core actions + +
            + +

            F.1.27 djopt

            + + +

            +
            djopt(debumpify|unjaggy|simple|vianudge|viatrim|orthopull)
            +djopt(auto) - all of the above
            +djopt(miter)
            +
            + +

            Perform various optimizations on the current board. + + +

            The different types of optimizations change your board in order to +reduce the total trace length and via count. + +

            +
            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. + +
            + +
            + +


            +Next: , +Previous: djopt Action, +Up: core actions + +
            + +

            F.1.28 DRC

            + + +

            +
            DRC()
            +
            + +

            Invoke the DRC check. + + +

            Note that the design rule check uses the current board rule settings, +not the current style settings. + +

            + +


            +Next: , +Previous: DRC Action, +Up: core actions + +
            + +

            F.1.29 DumpLibrary

            + + +

            +
            DumpLibrary()
            +
            + +

            Display the entire contents of the libraries. + + +

            + +


            +Next: , +Previous: DumpLibrary Action, +Up: core actions + +
            + +

            F.1.30 elementlist

            + + +

            +
            ElementList(Start|Done|Need,<refdes>,<footprint>,<value>)
            +
            + +

            Adds the given element if it doesn't already exist. + + +

            +
            Start
            Indicates the start of an element list; call this before any Need +actions. + +
            Need
            Searches the board for an element with a matching refdes. + +

            If found, the value and footprint are updated. + +

            If not found, a new element is created with the given footprint and value. + +

            Done
            Compares the list of elements needed since the most recent +start with the list of elements actually on the board. Any +elements that weren't listed are selected, so that the user may delete +them. + +
            + +
            + +


            +Next: , +Previous: elementlist Action, +Up: core actions + +
            + +

            F.1.31 elementsetattr

            + + +

            +
            ElementSetAttr(refdes,name[,value])
            +
            + +

            Sets or clears an element-specific attribute. + + +

            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. + +

            + +


            +Next: , +Previous: elementsetattr Action, +Up: core actions + +
            + +

            F.1.32 EnableVendor

            + + +

            +
            EnableVendor()
            +
            + +

            Enables automatic drill size mapping. + + +

            +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. To enable drill +mapping, a vendor resource file containing a drill table must be +loaded first. + +

            + +


            +Next: , +Previous: EnableVendor Action, +Up: core actions + +
            + +

            F.1.33 execcommand

            + + +

            +
            ExecCommand(command)
            +
            + +

            Runs a command. + + +

            Runs the given command, which is a system executable. + +

            + +


            +Next: , +Previous: execcommand Action, +Up: core actions + +
            + +

            F.1.34 ExecuteFile

            + + +

            +
            ExecuteFile(filename)
            +
            + +

            Run actions from the given file. + + +

            Lines starting with # are ignored. + +

            + +


            +Next: , +Previous: ExecuteFile Action, +Up: core actions + +
            + +

            F.1.35 Flip

            + + +

            +
            Flip(Object|Selected|SelectedElements)
            +
            + +

            Flip an element to the opposite side of the board. + + +

            Note that the location of the element 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 element is on the other side. When flipping +multiple elements, this retains their positions relative to each +other, not their absolute positions on the board. + +

            + +


            +Next: , +Previous: Flip Action, +Up: core actions + +
            + +

            F.1.36 FontEdit

            + + +

            +
            FontEdit()
            +
            + +

            Convert the current font to a PCB for editing. + + +

            + +


            +Next: , +Previous: FontEdit Action, +Up: core actions + +
            + +

            F.1.37 FontSave

            + + +

            +
            FontSave()
            +
            + +

            Convert the current PCB back to a font. + + +

            + +


            +Next: , +Previous: FontSave Action, +Up: core actions + +
            + +

            F.1.38 FreeRotateBuffer

            + + +

            +
            FreeRotateBuffer([Angle])
            +
            + +

            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. + + +

            Rotates the contents of the pastebuffer by an arbitrary angle. If no +angle is given, the user is prompted for one. + +

            + +


            +Next: , +Previous: FreeRotateBuffer Action, +Up: core actions + +
            + +

            F.1.39 GlobalPuller

            + + +

            +
            GlobalPuller()
            +
            + +

            Pull all traces tight. + + +

            + +


            +Next: , +Previous: GlobalPuller Action, +Up: core actions + +
            + +

            F.1.40 h

            + + +

            +
            h
            +
            + +

            Print a help message for commands. + + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: h Action, +Up: core actions + +
            + +

            F.1.41 Import

            + + +

            +
            Import()
            +Import([gnetlist|make[,source,source,...]])
            +Import(setnewpoint[,(mark|center|X,Y)])
            +Import(setdisperse,D,units)
            +
            +
            + +

            Import schematics. + + +

            Imports element 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 PCB is used. +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-rnd actions. By default, this is a temporary file +selected by pcb-rnd, 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 may be +overridden by the user via the make-program and gnetlist +pcb settings (i.e. in ~/.pcb/settings or on the command +line). + +

            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, elements +which shouldn't be on the board are selected and may be removed once +it's determined that the deletion is appropriate. + +

            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. + +

            +
            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. Example: +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 elements 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. + +

            + +


            +Next: , +Previous: Import Action, +Up: core actions + +
            + +

            F.1.42 l

            + + +

            +
            l [name]
            +
            + +

            Loads layout data. + + +

            Loads a new datafile (layout) and, if confirmed, overwrites any +existing unsaved data. The filename and the searchpath +(filePath) are passed to the command defined by +fileCommand. If no filename is specified a file select box +will popup. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: l Action, +Up: core actions + +
            + +

            F.1.43 le

            + + +

            +
            le [name]
            +
            + +

            Loads an element into the current buffer. + + +

            The filename and the searchpath (elementPath) are passed to the +command defined by elementCommand. If no filename is specified +a file select box will popup. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: le Action, +Up: core actions + +
            + +

            F.1.44 LoadFootprint

            + + +

            +
            LoadFootprint(filename[,refdes,value])
            +
            + +

            Loads a single footprint by name. + + +

            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. + +

            + +


            +Next: , +Previous: LoadFootprint Action, +Up: core actions + +
            + +

            F.1.45 LoadFrom

            + + +

            +
            LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename)
            +
            + +

            Load layout data from a file. + + +

            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. + +

            +
            Layout
            Loads an entire PCB layout, replacing the current one. + +
            LayoutToBuffer
            Loads an entire PCB layout to the paste buffer. + +
            ElementToBuffer
            Loads the given element file into the paste buffer. Element files +contain only a single Element definition, such as the +“newlib” library uses. + +
            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. + +
            + +
            + +


            +Next: , +Previous: LoadFrom Action, +Up: core actions + +
            + +

            F.1.46 LoadVendorFrom

            + + +

            +
            LoadVendorFrom(filename)
            +
            + +

            Loads the specified vendor resource file. + + +

            +

            +
            filename
            Name of the vendor resource file. If not specified, the user will +be prompted to enter one. +
            + +
            + +


            +Next: , +Previous: LoadVendorFrom Action, +Up: core actions + +
            + +

            F.1.47 m

            + + +

            +
            m [name]
            +
            + +

            Loads a layout into the current buffer. + + +

            The filename and the searchpath (filePath) are passed to the +command defined by fileCommand. +If no filename is specified a file select box will popup. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: m Action, +Up: core actions + +
            + +

            F.1.48 MarkCrosshair

            + + +

            +
            MarkCrosshair()
            +MarkCrosshair(Center)
            +
            + +

            Set/Reset the Crosshair mark. + + +

            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. + +

            + +


            +Next: , +Previous: MarkCrosshair Action, +Up: core actions + +
            + +

            F.1.49 Message

            + + +

            +
            Message(message)
            +
            + +

            Writes a message to the log window. + + +

            This action displays a message to the log window. This action is primarily +provided for use by other programs which may interface with PCB. If +multiple arguments are given, each one is sent to the log window +followed by a newline. + +

            + +


            +Next: , +Previous: Message Action, +Up: core actions + +
            + +

            F.1.50 MinClearGap

            + + +

            +
            MinClearGap(delta)
            +MinClearGap(Selected, delta)
            +
            + +

            Ensures that polygons are a minimum distance from objects. + + +

            Checks all specified objects, and increases the polygon clearance if +needed to ensure a minimum distance between their edges and the +polygon edges. + +

            + +


            +Next: , +Previous: MinClearGap Action, +Up: core actions + +
            + +

            F.1.51 MinMaskGap

            + + +

            +
            MinMaskGap(delta)
            +MinMaskGap(Selected, delta)
            +
            + +

            Ensures the mask is a minimum distance from pins and pads. + + +

            Checks all specified pins and/or pads, and increases the mask if +needed to ensure a minimum distance between the pin or pad edge and +the mask edge. + +

            + +


            +Next: , +Previous: MinMaskGap Action, +Up: core actions + +
            + +

            F.1.52 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)
            +
            + +

            Change or use the tool mode. + + +

            +
            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 your pcb 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. + +
            + +
            + +


            +Next: , +Previous: Mode Action, +Up: core actions + +
            + +

            F.1.53 MorphPolygon

            + + +

            +
            MorphPolygon(Object|Selected)
            +
            + +

            Converts dead polygon islands into separate polygons. + + +

            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. + +

            + +


            +Next: , +Previous: MorphPolygon Action, +Up: core actions + +
            + +

            F.1.54 MoveLayer

            + + +

            +
            MoveLayer(old,new)
            +
            + +

            Moves/Creates/Deletes Layers. + + +

            Moves a layer, creates a new layer, or deletes a layer. + +

            +
            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. + +
            down
            Moves the layer down. + +
            c
            Creates a new layer. + +
            + +
            + +
            + +


            +Next: , +Previous: MoveLayer Action, +Up: core actions + +
            + +

            F.1.55 MoveObject

            + + +

            +
            MoveObject(X,Y,dim)
            +
            + +

            Moves the object under the crosshair. + + +

            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. Otherwise, it's absolute. Units can be +mil or mm; if unspecified, units are PCB's internal +units, currently 1/100 mil. + +

            + +


            +Next: , +Previous: MoveObject Action, +Up: core actions + +
            + +

            F.1.56 MoveToCurrentLayer

            + + +

            +
            MoveToCurrentLayer(Object|SelectedObjects)
            +
            + +

            Moves objects to the current layer. + + +

            Note that moving an element 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. + +

            + +


            +Next: , +Previous: MoveToCurrentLayer Action, +Up: core actions + +
            + +

            F.1.57 Netlist

            + + +

            +
            Net(find|select|rats|norats|clear[,net[,pin]])
            +Net(freeze|thaw|forcethaw)
            +Net(add,net,pin)
            +
            + +

            Perform various actions on netlists. + + +

            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. + +

            +
            find
            Nets which apply are marked found and are drawn in the +connected-color color. + +
            select
            Nets which apply are selected. + +
            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. + +
            add
            Add the given pin to the given netlist, creating either if needed. + +
            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. 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. + +
            + +
            + +


            +Next: , +Previous: Netlist Action, +Up: core actions + +
            + +

            F.1.58 New

            + + +

            +
            New([name])
            +
            + +

            Starts a new layout. + + +

            If a name is not given, one is prompted for. + +

            + +


            +Next: , +Previous: New Action, +Up: core actions + +
            + +

            F.1.59 OptAutoOnly

            + + +

            +
            OptAutoOnly()
            +
            + +

            Toggles the optimize-only-autorouted flag. + + +

            The original purpose of the trace optimizer was to clean up the traces +created by the various autorouters that have been used with PCB. When +a board has a mix of autorouted and carefully hand-routed traces, you +don't normally want the optimizer to move your hand-routed traces. +But, sometimes you do. By default, the optimizer only optimizes +autorouted traces. This action toggles that setting, so that you can +optimize hand-routed traces also. + +

            + +


            +Next: , +Previous: OptAutoOnly Action, +Up: core actions + +
            + +

            F.1.60 PasteBuffer

            + + +

            +
            PasteBuffer(AddSelected|Clear|1..MAX_BUFFER)
            +PasteBuffer(Rotate, 1..3)
            +PasteBuffer(Convert|Save|Restore|Mirror)
            +PasteBuffer(ToLayout, X, Y, units)
            +
            + +

            Various operations on the paste buffer. + + +

            There are a number of paste buffers; the actual limit is a +compile-time constant MAX_BUFFER in globalconst.h. It +is currently 5. One of these is the “current” paste buffer, +often referred to as “the” paste buffer. + +

            +
            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 element. Vias are converted to +pins, lines are converted to pads. + +
            Restore
            Convert any elements in the paste buffer back to vias and lines. + +
            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). + +
            Save
            Saves any elements in the current buffer to the indicated file. + +
            ToLayout
            Pastes any elements 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. Units can be +mil or mm; if unspecified, units are PCB's internal +units, currently 1/100 mil. + +
            1..MAX_BUFFER
            Selects the given buffer to be the current paste buffer. + +
            + +
            + +


            +Next: , +Previous: PasteBuffer Action, +Up: core actions + +
            + +

            F.1.61 Polygon

            + + +

            +
            Polygon(Close|PreviousPoint)
            +
            + +

            Some polygon related stuff. + + +

            Polygons need a special action routine to make life easier. + +

            +
            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. + +
            PreviousPoint
            Resets the newly entered corner to the previous one. The Undo action +will call Polygon(PreviousPoint) when appropriate to do so. + +
            + +
            + +


            +Next: , +Previous: Polygon Action, +Up: core actions + +
            + +

            F.1.62 Puller

            + + +

            +
            Puller()
            +
            + +

            Pull an arc-line junction tight. + + +

            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. In the example below, +the left side is “before” with the black target marking where to put +the crosshair: + +

            Example of how puller works
            + +

            The right side is “after” with the black target marking where the +arc-line intersection was moved to. + +

            + +


            +Next: , +Previous: Puller Action, +Up: core actions + +
            + +

            F.1.63 q

            + + +

            +
            q
            +
            + +

            Quits the application after confirming. + + +

            If you have unsaved changes, you will be prompted to confirm (or +save) before quitting. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + + +


            +Next: , +Previous: q Action, +Up: core actions + +
            + +

            F.1.64 q!

            + + +

            +
            q!
            +
            + +

            Quits the application without confirming. + + +

            Note that this command neither saves your data nor prompts for +confirmation. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: q! Action, +Up: core actions + +
            + +

            F.1.65 Quit

            + + +

            +
            Quit()
            +
            + +

            Quits the application after confirming. + + +

            If you have unsaved changes, you will be prompted to confirm (or +save) before quitting. + +

            + +


            +Next: , +Previous: Quit Action, +Up: core actions + +
            + +

            F.1.66 Redo

            + + +

            +
            Redo()
            +
            + +

            Redo recent“undo”operations. + + +

            This routine 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. + +

            + +


            +Next: , +Previous: Redo Action, +Up: core actions + +
            + +

            F.1.67 RemoveSelected

            + + +

            +
            RemoveSelected()
            +
            + +

            Removes any selected objects. + + +

            + +


            +Next: , +Previous: RemoveSelected Action, +Up: core actions + +
            + +

            F.1.68 Renumber

            + + +

            +
            Renumber()
            +Renumber(filename)
            +
            + +

            Renumber all elements. The changes will be recorded to filename +for use in backannotating these changes to the schematic. + + +

            + +


            +Next: , +Previous: Renumber Action, +Up: core actions + +
            + +

            F.1.69 Report

            + + +

            +
            Report(Object|DrillReport|FoundPins|NetLength|AllNetLengths|[,name])
            +
            + +

            Produce various report. + + +

            +
            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 + +
            + +
            + +


            +Next: , +Previous: Report Action, +Up: core actions + +
            + +

            F.1.70 ReportDialog

            + + +

            +
            ReportDialog()
            +
            + +

            Report on the object under the crosshair + + +

            This is a shortcut for Report(Object). + +

            + +


            +Next: , +Previous: ReportDialog Action, +Up: core actions + +
            + +

            F.1.71 RipUp

            + + +

            +
            RipUp(All|Selected|Element)
            +
            + +

            Ripup auto-routed tracks, or convert an element to parts. + + +

            +
            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. + +
            Element
            Converts the element under the cursor to parts (vias and lines). Note +that this uses the highest numbered paste buffer. + +
            + +
            + +


            +Next: , +Previous: RipUp Action, +Up: core actions + +
            + +

            F.1.72 rn

            + + +

            +
            rn [name]
            +
            + +

            Reads netlist. + + +

            If no filename is given a file select box will pop up. The file is +read via the command defined by the RatCommand resource. The +command must send its output to stdout. + +

            Netlists are used for generating rat's nests (see Rats Nest) and +for verifying the board layout (which is also accomplished by the +Ratsnest command). + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: rn Action, +Up: core actions + +
            + +

            F.1.73 RouteStyle

            + + +

            +
            RouteStyle(1|2|3|4)
            +
            + +

            Copies the indicated routing style into the current sizes. + + +

            + +


            +Next: , +Previous: RouteStyle Action, +Up: core actions + +
            + +

            F.1.74 s

            + + +

            +
            s [name]
            +
            + +

            Saves layout data. + + +

            Data and the filename are passed to the command defined by the +resource saveCommand. It must read the layout data from +stdin. 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. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: s Action, +Up: core actions + +
            + +

            F.1.75 SaveSettings

            + + +

            +
            SaveSettings()
            +SaveSettings(local)
            +
            + +

            Saves settings. + + +

            If you pass no arguments, the settings are stored in +$HOME/.pcb/settings. If you pass the word local they're +saved in ./pcb.settings. + +

            + +


            +Next: , +Previous: SaveSettings Action, +Up: core actions + +
            + +

            F.1.76 SaveTo

            + + +

            +
            SaveTo(Layout|LayoutAs,filename)
            +SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)
            +SaveTo(PasteBuffer,filename)
            +
            + +

            Saves data to a file. + + +

            +
            Layout
            Saves the current layout. + +
            LayoutAs
            Saves the current layout, and remembers the filename used. + +
            AllConnections
            Save all connections to a file. + +
            AllUnusedPins
            List all unused pins to a file. + +
            ElementConnections
            Save connections to the element at the cursor to a file. + +
            PasteBuffer
            Save the content of the active Buffer to a file. This is the graphical way to create a footprint. + +
            + +
            + +


            +Next: , +Previous: SaveTo Action, +Up: core actions + +
            + +

            F.1.77 Select

            + + +

            +
            Select(Object|ToggleObject)
            +Select(All|Block|Connection)
            +Select(ElementByName|ObjectByName|PadByName|PinByName)
            +Select(ElementByName|ObjectByName|PadByName|PinByName, Name)
            +Select(TextByName|ViaByName|NetByName)
            +Select(TextByName|ViaByName|NetByName, Name)
            +Select(Convert)
            +
            + +

            Toggles or sets the selection. + + +

            +
            ElementByName
            ObjectByName
            PadByName
            PinByName
            TextByName
            ViaByName
            NetByName
            +These all rely on having a regular expression parser built into +pcb. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are selected. + +
            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 an element. This uses the highest +numbered paste buffer. + +
            + +
            + +


            +Next: , +Previous: Select Action, +Up: core actions + +
            + +

            F.1.78 SetFlag

            + + +

            +
            SetFlag(Object|Selected|SelectedObjects, flag)
            +SetFlag(SelectedLines|SelectedPins|SelectedVias, flag)
            +SetFlag(SelectedPads|SelectedTexts|SelectedNames, flag)
            +SetFlag(SelectedElements, flag)
            +flag = square | octagon | thermal | join
            +
            + +

            Sets flags on objects. + + +

            Turns the given flag on, regardless of its previous setting. See +ChangeFlag. + +

                 SetFlag(SelectedPins,thermal)
            +
            +
            + +


            +Next: , +Previous: SetFlag Action, +Up: core actions + +
            + +

            F.1.79 SetOctagon

            + + +

            +
            SetOctagon(Object|ToggleObject|SelectedElements|Selected)
            +
            + +

            Sets the octagon-flag of objects. + + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: SetOctagon Action, +Up: core actions + +
            + +

            F.1.80 SetSame

            + + +

            +
            SetSame()
            +
            + +

            Sets current layer and sizes to match indicated item. + + +

            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, keepaway, drill, etc) according to that item. + +

            + +


            +Next: , +Previous: SetSame Action, +Up: core actions + +
            + +

            F.1.81 SetSquare

            + + +

            +
            SetSquare(ToggleObject|SelectedElements|SelectedPins)
            +
            + +

            sets the square-flag of objects. + + +

            Note that Pins means pins and pads. + +

            Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +

            Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +

            + +


            +Next: , +Previous: SetSquare Action, +Up: core actions + +
            + +

            F.1.82 SetThermal

            + + +

            +
            SetThermal(Object|SelectedPins|SelectedVias|Selected, Style)
            +
            + +

            Set the thermal (on the current layer) of pins or vias 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. + + +

            This changes how/whether pins or vias connect to any rectangle or polygon +on the current layer. The first argument can specify one object, or all +selected pins, or all selected vias, or all selected pins and vias. +The second argument specifies the style of connection. +There are 5 possibilities: +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. + +

            Pins and Vias may have thermals whether or not there is a polygon available +to connect with. However, they will have no effect without the polygon. + +

            + +


            +Next: , +Previous: SetThermal Action, +Up: core actions + +
            + +

            F.1.83 SetValue

            + + +

            +
            SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)
            +
            + +

            Change various board-wide values and sizes. + + +

            +
            ViaDrillingHole
            Changes the diameter of the drill for new vias. + +
            Grid
            Sets the grid spacing. + +
            Line
            LineSize
            Changes the thickness of new lines. + +
            Via
            ViaSize
            Changes the diameter of new vias. + +
            Text
            TextScale
            Changes the size of new text. + +
            + +
            + +


            +Next: , +Previous: SetValue Action, +Up: core actions + +
            + +

            F.1.84 ToggleHideName

            + + +

            +
            ToggleHideName(Object|SelectedElements)
            +
            + +

            Toggles the visibility of element names. + + +

            If names are hidden you won't see them on the screen and they will not +appear on the silk layer when you print the layout. + +

            + +


            +Next: , +Previous: ToggleHideName Action, +Up: core actions + +
            + +

            F.1.85 ToggleVendor

            + + +

            +
            ToggleVendor()
            +
            + +

            Toggles the state of automatic drill size mapping. + + +

            +When drill mapping is enabled, new instances of pins and vias will +have their drill holes mapped to one of the allowed drill sizes +specified in the currently loaded vendor drill table. To enable drill +mapping, a vendor resource file containing a drill table must be +loaded first. + +

            + +


            +Next: , +Previous: ToggleVendor Action, +Up: core actions + +
            + +

            F.1.86 Undo

            + + +

            +
            Undo()
            +Undo(ClearList)
            +
            + +

            Undo recent changes. + + +

            The unlimited undo feature of pcb-rnd allows you to recover from +most operations that materially affect you work. Calling +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 and Atomic. + +

            Note that undo groups operations by serial number; changes with the +same serial number will be undone (or redone) as a group. See +Atomic. + +

            + +


            +Next: , +Previous: Undo Action, +Up: core actions + +
            + +

            F.1.87 UnloadVendor

            + + +

            +
            UnloadVendor()
            +
            + +

            Unloads the current vendor drill mapping table. + + +

            + +

            + +


            +Next: , +Previous: UnloadVendor Action, +Up: core actions + +
            + +

            F.1.88 Unselect

            + + +

            +
            Unselect(All|Block|Connection)
            +Unselect(ElementByName|ObjectByName|PadByName|PinByName)
            +Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)
            +Unselect(TextByName|ViaByName)
            +Unselect(TextByName|ViaByName, Name)
            +
            +
            + +

            Unselects the object at the pointer location or the specified objects. + + +

            +
            All
            Unselect all objects. + +
            Block
            Unselect all objects in a rectangle given by the cursor. + +
            Connection
            Unselect all connections with the “found” flag set. + +
            ElementByName
            ObjectByName
            PadByName
            PinByName
            TextByName
            ViaByName
            +These all rely on having a regular expression parser built into +pcb. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are unselected. + +
            + +
            + +


            +Next: , +Previous: Unselect Action, +Up: core actions + +
            + +

            F.1.89 w

            + + +

            +
            w [name]
            +
            + +

            Saves layout data. + + +

            This commands has been added for the convenience of vi users +and has the same functionality as s. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Previous: w Action, +Up: core actions + +
            + +

            F.1.90 wq

            + + +

            +
            wq
            +
            + +

            Saves the layout data and quits. + + +

            This command has been added for the convenience of vi users and +has the same functionality as s combined with q. + +

            This is one of the command box helper actions. While it is a regular +action and can be used like any other action, its name and syntax are +optimized for use with the command box (:) and thus the syntax +is documented for that purpose. + +

            + +


            +Next: , +Previous: core actions, +Up: Action Reference + +
            + +

            F.2 common actions

            + + + +
            + +


            +Next: , +Up: common actions + +
            + +

            F.2.1 LayersChanged

            + + +

            +
            LayersChanged()
            +
            + +

            Tells the GUI that the layers have changed. + + +

            This includes layer names, colors, stacking order, visibility, etc. + +

            This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +

            + +


            +Next: , +Previous: LayersChanged Action, +Up: common actions + +
            + +

            F.2.2 LibraryChanged

            + + +

            +
            LibraryChanged()
            +
            + +

            Tells the GUI that the libraries have changed. + + +

            This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +

            + +


            +Next: , +Previous: LibraryChanged Action, +Up: common actions + +
            + +

            F.2.3 NetlistChanged

            + + +

            +
            NetlistChanged()
            +
            + +

            Tells the GUI that the netlist has changed. + + +

            This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +

            + +

            F.2.4 PCBChanged

            + + +

            +
            PCBChanged([revert])
            +
            + +

            Tells 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 settings + + +

            This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +

            + +


            +Previous: PCBChanged Action, +Up: common actions + +
            + +

            F.2.5 RouteStylesChanged

            + + +

            +
            RouteStylesChanged()
            +
            + +

            Tells the GUI that the routing styles have changed. + + +

            This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +

            + +


            +Next: , +Previous: common actions, +Up: Action Reference + +
            + +

            F.3 gtk actions

            + + +
            + +


            +Next: , +Up: gtk actions + +
            + +

            F.3.1 gtk About

            + + +

            +
            About()
            +
            + +

            N_("Tell the user about this version of PCB."); + + +

            This just pops up a dialog telling the user which version of +pcb they're running. + +

            + +


            +Next: , +Previous: gtk About Action, +Up: gtk actions + +
            + +

            F.3.2 gtk AdjustStyle

            + + +

            +
            AdjustStyle()
            +
            +
            + +

            Open the window which allows editing of the route styles. + + +

            Opens the window which allows editing of the route styles. + +

            + +


            +Next: , +Previous: gtk AdjustStyle Action, +Up: gtk actions + +
            + +

            F.3.3 gtk Center

            + + +

            +
            Center()
            +
            +
            + +

            N_("Moves the pointer to the center of the window."); + + +

            Move the pointer to the center of the window, but only if it's +currently within the window already. + +

            + +


            +Next: , +Previous: gtk Center Action, +Up: gtk actions + +
            + +

            F.3.4 gtk Cursor

            + + +

            +
            Cursor(Type,DeltaUp,DeltaRight,Units)
            +
            + +

            N_("Move the cursor."); + + +

            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 towards the board origin if the board is inverted. + +

            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. + +
            + +
            + +


            +Next: , +Previous: gtk Cursor Action, +Up: gtk actions + +
            + +

            F.3.5 gtk DoWindows

            + + +

            +
            DoWindows(1|2|3|4|5|6)
            +DoWindows(Layout|Library|Log|Netlist|Preferences|DRC)
            +
            + +

            N_("Open various GUI windows."); + + +

            +
            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. + +
            + +
            + +


            +Next: , +Previous: gtk DoWindows Action, +Up: gtk actions + +
            + +

            F.3.6 gtk EditLayerGroups

            + + +

            +
            EditLayerGroups()
            +
            +
            + +

            Open the preferences window which allows editing of the layer groups. + + +

            Opens the preferences window which is where the layer groups +are edited. This action is primarily provides to provide menu +resource compatibility with the lesstif HID. + +

            + +


            +Next: , +Previous: gtk EditLayerGroups Action, +Up: gtk actions + +
            + +

            F.3.7 gtk GetXY

            + + +

            +
            GetXY()
            +
            + +

            N_("Get a coordinate."); + + +

            Prompts the user for a coordinate, if one is not already selected. + +

            + +


            +Next: , +Previous: gtk GetXY Action, +Up: gtk actions + +
            + +

            F.3.8 gtk ImportGUI

            + + +

            +
            ImportGUI()
            +
            + +

            N_("Asks user which schematics to import into PCB. +"); + + +

            Asks user which schematics to import into PCB. + +

            + +


            +Next: , +Previous: gtk ImportGUI Action, +Up: gtk actions + +
            + +

            F.3.9 gtk Pan

            + + +

            +
            Pan([thumb], Mode)
            +
            + +

            N_("Start or stop panning (Mode = 1 to start, 0 to stop) +Optional thumb argument is ignored for now in gtk hid. +"); + + +

            Start or stop panning. To start call with Mode = 1, to stop call with +Mode = 0. + +

            + +


            +Next: , +Previous: gtk Pan Action, +Up: gtk actions + +
            + +

            F.3.10 gtk Popup

            + + +

            +
            Popup(MenuName, [Button])
            +
            + +

            N_("Bring up the popup menu specified by MenuName. +If called by a mouse event then the mouse button number +must be specified as the optional second argument."); + + +

            This just pops up the specified menu. The menu must have been defined +as a named subresource of the Popups resource in the menu resource +file. + +

            + +


            +Next: , +Previous: gtk Popup Action, +Up: gtk actions + +
            + +

            F.3.11 gtk Print

            + + +

            +
            Print()
            +
            + +

            N_("Print the layout."); + + +

            This will find the default printing HID, prompt the user for its +options, and print the layout. + +

            + +


            +Next: , +Previous: gtk Print Action, +Up: gtk actions + +
            + +

            F.3.12 gtk PrintCalibrate

            + + +

            +
            PrintCalibrate()
            +
            + +

            N_("Calibrate the printer."); + + +

            This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. + +

            + +


            +Next: , +Previous: gtk PrintCalibrate Action, +Up: gtk actions + +
            + +

            F.3.13 gtk Save

            + + +

            +
            Save()
            +Save(Layout|LayoutAs)
            +Save(AllConnections|AllUnusedPins|ElementConnections)
            +Save(PasteBuffer)
            +
            + +

            N_("Save layout and/or element data to a user-selected file."); + + +

            This action is a GUI front-end to the core's SaveTo action +(see SaveTo Action). If you happen to pass a filename, like +SaveTo, then SaveTo is called directly. Else, the +user is prompted for a filename to save, and then SaveTo is +called with that filename. + +

            + +


            +Next: , +Previous: gtk Save Action, +Up: gtk actions + +
            + +

            F.3.14 gtk SelectLayer

            + + +

            +
            SelectLayer(1..MAXLAYER|Silk|Rats)
            +
            + +

            Select which layer is the current layer. + + +

            The specified layer becomes the currently active layer. It is made +visible if it is not already visible + +

            + +


            +Next: , +Previous: gtk SelectLayer Action, +Up: gtk actions + +
            + +

            F.3.15 gtk SetUnits

            + + +

            +
            SetUnits(mm|mil)
            +
            + +

            N_("Set the default measurement units."); + + +

            +
            mil
            Sets the display units to mils (1/1000 inch). + +
            mm
            Sets the display units to millimeters. + +
            + +
            + +


            +Next: , +Previous: gtk SetUnits Action, +Up: gtk actions + +
            + +

            F.3.16 gtk SwapSides

            + + +

            +
            SwapSides(|v|h|r)
            +
            + +

            N_("Swaps the side of the board you're looking at."); + + +

            This action changes the way you view the board. + +

            +
            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 +true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. + +

            As a special case, 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. + +

            + +


            +Next: , +Previous: gtk SwapSides Action, +Up: gtk actions + +
            + +

            F.3.17 gtk ToggleView

            + + +

            +
            ToggleView(1..MAXLAYER)
            +ToggleView(layername)
            +ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)
            +
            + +

            Toggle the visibility of the specified layer or layer group. + + +

            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. + +

            + +


            +Previous: gtk ToggleView Action, +Up: gtk actions + +
            + +

            F.3.18 gtk Zoom

            + + +

            +
            Zoom()
            +Zoom(factor)
            +
            + +

            N_("Various zoom factor changes."); + +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 ++, -, or = to change how the zoom factor is +modified. The factor is a floating point number, such as +1.5 or 0.75. + +

            + +
            +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 factor is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +factor of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a factor of 100 gives you a 10x actual +size. + +
            + +

            Note that zoom factors of zero are silently ignored. + +

            + +


            +Previous: gtk actions, +Up: Action Reference + +
            + +

            F.4 lesstif actions

            + + + + +

            F.4.1 lesstif About

            + + +

            +
            About()
            +
            + +

            Tell the user about this version of PCB. + + +

            This just pops up a dialog telling the user which version of +pcb they're running. + +

            + +

            F.4.2 lesstif AdjustSizes

            + + +

            +
            AdjustSizes()
            +
            + +

            Let the user change the board size, DRC parameters, etc + + +

            Displays a dialog box that lets the user change the board +size, DRC parameters, and text scale. + +

            The units are determined by the default display units. + +

            + +

            F.4.3 lesstif AdjustStyle

            + + +

            +
            AdjustStyle()
            +
            + +

            Displays the route style adjustment window. + + +

            + +

            F.4.4 lesstif Benchmark

            + + +

            +
            Benchmark()
            +
            + +

            Benchmark the GUI speed. + + +

            This action is used to speed-test the Lesstif graphics subsystem. 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. + +

            + +

            F.4.5 lesstif Command

            + + +

            +
            Command()
            +
            + +

            Displays the command line input window. + + +

            The command window allows the user to manually enter actions to be +executed. Action syntax can be done one of two ways: + +

            +
            Follow the action name by an open parenthesis, arguments separated by +commas, end with a close parenthesis. Example: Abc(1,2,3) + +
            Separate the action name and arguments by spaces. Example: Abc +1 2 3. + +
            + +

            The first option allows you to have arguments with spaces in them, +but the second is more “natural” to type for most people. + +

            Note that action names are not case sensitive, but arguments normally +are. However, most actions will check for “keywords” in a case +insensitive way. + +

            There are three ways to finish with the command window. If you press +the Enter key, the command is invoked, the window 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. If you change focus away from the command window (i.e. click +on some other window), the command window goes away but the next time +you bring it up it resumes entering the command you were entering +before. + +

            + +


            +Next: , +Previous: lesstif Command Action, +Up: lesstif actions + +
            + +

            F.4.6 lesstif Cursor

            + + +

            +
            Cursor(Type,DeltaUp,DeltaRight,Units)
            +
            + +

            Move the cursor. + + +

            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 towards the board origin if the board is inverted. + +

            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. + +
            + +
            + +


            +Next: , +Previous: lesstif Cursor Action, +Up: lesstif actions + +
            + +

            F.4.7 lesstif Debug

            + + +

            +
            Debug(...)
            +
            + +

            Debug action. + + +

            This action exists to help debug scripts; it simply prints all its +arguments to stdout. + +

            + +

            F.4.8 lesstif DebugXY

            + + +

            +
            DebugXY(...)
            +
            + +

            Debug action, with coordinates + + +

            Like Debug, but requires a coordinate. If the user hasn't yet +indicated a location on the board, the user will be prompted to click +on one. + +

            + +

            F.4.9 lesstif DoWindows

            + + +

            +
            DoWindows(1|2|3|4)
            +DoWindows(Layout|Library|Log|Netlist)
            +
            + +

            Open various GUI windows. + + +

            +
            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. + +
            + + + +

            F.4.10 lesstif DumpKeys

            + + +

            +
            DumpKeys()
            +
            + +

            Dump Lesstif key bindings. + + +

            Causes the list of key bindings (from pcb-menu.res) to be +dumped to stdout. This is most useful when invoked from the command +line like this: + +

                 pcb --action-string DumpKeys
            +
            + + +

            F.4.11 lesstif EditLayerGroups

            + + +

            +
            EditLayerGroups()
            +
            + +

            Let the user change the layer groupings + + +

            Displays a dialog that lets the user view and change the layer +groupings. Each layer (row) can be a member of any one layer group +(column). Note the special layers solder and component +allow you to specify which groups represent the top and bottom of the +board. + +

            See ChangeName Action. + +

            + +

            F.4.12 lesstif Export

            + + +

            +
            Export()
            +
            + +

            Export the layout. + + +

            Prompts the user for an exporter to use. Then, prompts the user for +that exporter's options, and exports the layout. + +

            + +

            F.4.13 lesstif GetXY

            + + +

            +
            GetXY()
            +
            + +

            Get a coordinate. + + +

            Prompts the user for a coordinate, if one is not already selected. + +

            + +

            F.4.14 lesstif ImportGUI

            + + +

            +
            ImportGUI()
            +
            + +

            Lets the user choose the schematics to import from + + +

            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. + +

            + +


            +Next: , +Previous: lesstif ImportGUI Action, +Up: lesstif actions + +
            + +

            F.4.15 lesstif LibraryShow

            + + +

            +
            LibraryShow()
            +
            + +

            Displays the library window. + + +

            + +

            F.4.16 lesstif Load

            + + +

            +
            Load()
            +Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)
            +
            + +

            Load layout data from a user-selected file. + + +

            This action is a GUI front-end to the core's LoadFrom action +(see LoadFrom Action). If you happen to pass a filename, like +LoadFrom, then LoadFrom is called directly. Else, the +user is prompted for a filename to load, and then LoadFrom is +called with that filename. + +

            + +

            F.4.17 lesstif LoadVendor

            + + +

            +
            LoadVendor()
            +
            + +

            Loads a user-selected vendor resource file. + + +

            The user is prompted for a file to load, and then +LoadVendorFrom is called (see LoadVendorFrom Action) to +load that vendor file. + +

            + +

            F.4.18 lesstif NetlistShow

            + + +

            +
            NetlistShow(pinname|netname)
            +
            + +

            Selects the given pinname or netname in the netlist window. + + +

            + +

            F.4.19 lesstif Print

            + + +

            +
            Print()
            +
            + +

            Print the layout. + + +

            This will find the default printing HID, prompt the user for its +options, and print the layout. + +

            + +

            F.4.20 lesstif PrintCalibrate

            + + +

            +
            PrintCalibrate()
            +
            + +

            Calibrate the printer. + + +

            This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. + +

            + +

            F.4.21 lesstif PromptFor

            + + +

            +
            PromptFor([message[,default]])
            +
            + +

            Prompt for a response. + + +

            This is mostly for testing the lesstif HID interface. The parameters +are passed to the prompt_for() HID function, causing the user +to be prompted for a response. The respose is simply printed to the +user's stdout. + +

            + +


            +Next: , +Previous: lesstif PromptFor Action, +Up: lesstif actions + +
            + +

            F.4.22 lesstif Return

            + + +

            +
            Return(0|1)
            +
            + +

            Simulate a passing or failing action. + + +

            This is for testing. If passed a 0, does nothing and succeeds. If +passed a 1, does nothing but pretends to fail. + +

            + +

            F.4.23 lesstif Save

            + + +

            +
            Save()
            +Save(Layout|LayoutAs)
            +Save(AllConnections|AllUnusedPins|ElementConnections)
            +Save(PasteBuffer)
            +
            + +

            Save layout data to a user-selected file. + + +

            This action is a GUI front-end to the core's SaveTo action +(see SaveTo Action). If you happen to pass a filename, like +SaveTo, then SaveTo is called directly. Else, the +user is prompted for a filename to save, and then SaveTo is +called with that filename. + +

            + +


            +Next: , +Previous: lesstif Save Action, +Up: lesstif actions + +
            + +

            F.4.24 lesstif SelectLayer

            + + +

            +
            SelectLayer(1..MAXLAYER|Silk|Rats)
            +
            + +

            Select which layer is the current layer. + + +

            The specified layer becomes the currently active layer. It is made +visible if it is not already visible + +

            + +

            F.4.25 lesstif SetUnits

            + + +

            +
            SetUnits(mm|mil)
            +
            + +

            Set the default measurement units. + + +

            +
            mil
            Sets the display units to mils (1/1000 inch). + +
            mm
            Sets the display units to millimeters. + +
            + + + +

            F.4.26 lesstif SwapSides

            + + +

            +
            SwapSides(|v|h|r)
            +
            + +

            Swaps the side of the board you're looking at. + + +

            This action changes the way you view the board. + +

            +
            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 +true silk, and which are drawn as the "invisible" layer. It also +determines which solder mask you see. + +

            As a special case, 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. + +

            + +


            +Next: , +Previous: lesstif SwapSides Action, +Up: lesstif actions + +
            + +

            F.4.27 lesstif ToggleView

            + + +

            +
            ToggleView(1..MAXLAYER)
            +ToggleView(layername)
            +ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)
            +
            + +

            Toggle the visibility of the specified layer or layer group. + + +

            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. + +

            + +


            +Previous: lesstif ToggleView Action, +Up: lesstif actions + +
            + +

            F.4.28 lesstif Zoom

            + + +

            +
            Zoom()
            +Zoom(factor)
            +
            + +

            Various zoom factor changes. + + +

            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 ++, -, or = to change how the zoom factor is +modified. The factor is a floating point number, such as +1.5 or 0.75. + +

            +
            +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 factor is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +factor of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a factor of 100 gives you a 10x actual +size. + +
            + +

            Note that zoom factors of zero are silently ignored. + + +

            + +


            +Next: , +Previous: Action Reference, +Up: Top + +
            + +

            Appendix G Glossary

            + +

            +

            +
            Footprint
            The pattern of metal, silkscreen, soldermask relief, and drills which +defines where you place a component on a circuit board. +Footprints are the placed by the user onto the PC board during the +placement phase of PCB layout. + +
            Gerber File
            The file format used in the industry to convey a board database to the +manufacturer is RS-274X (which replaces the now obsolete RS-274D +format). This file format was originally developed by Gerber for +their photo plotters and thus RS-274D and RS-274X format files +are often times refered to as “Gerber” files. + +
            Thermal, Thermal Relief
            A thermal relief is a way of connecting a pin to a ground +or power plane. Instead of directly connecting to the plane, small "spokes" +are used to increase the thermal resistance between the pin and the plane. +Often times these connections are refered to as simply a thermal. By increasing +the thermal resistance to the plane, it becomes easier to solder to the +pin. In the drawing below, the pin on the left is connected to the +polygon using a solid connection with no thermal relief, the middle +pin is connected using a thermal, while the pin on the right has no +connection to the polygon. In PCB, the “Thermal” Tool is used to +make both a solid connection and one with thermal relief (see Polygon Objects). + +
            Example of a thermal relief
            + +
            + + +
            + +


            +Previous: Glossary, +Up: Top + +
            + +

            Index of Resources

            + +

            Index of Actions, Commands and Options

            + + + +

            Index of Concepts

            + + + + +
            +

            Table of Contents

            + +
            + + + Index: tags/1.2.7/doc-orig/pcbfile.texi =================================================================== --- tags/1.2.7/doc-orig/pcbfile.texi (nonexistent) +++ tags/1.2.7/doc-orig/pcbfile.texi (revision 13657) @@ -0,0 +1,946 @@ +@c key pcbfile +@c ./../src/parse_y.y 143 + +A special note about units: Older versions of @code{pcb} used mils +(1/1000 inch) as the base unit; a value of 500 in the file meant +half an inch. Newer versions uses a "high resolution" syntax, +where the base unit is 1/100 of a mil (0.000010 inch); a value of 500 in +the file means 5 mils. As a general rule, the variants of each entry +listed below which use square brackets are the high resolution formats +and use the 1/100 mil units, and the ones with parentheses are the older +variants and use 1 mil units. Note that when multiple variants +are listed, the most recent (and most preferred) format is the first +listed. + +Symbolic and numeric flags (SFlags and NFlags) are described in +@ref{Object Flags}. + +@menu +* Arc syntax:: +* Attribute syntax:: +* Connect syntax:: +* Cursor syntax:: +* DRC syntax:: +* Element syntax:: +* ElementArc syntax:: +* ElementLine syntax:: +* FileVersion syntax:: +* Flags syntax:: +* Grid syntax:: +* Groups syntax:: +* Layer syntax:: +* Line syntax:: +* Mark syntax:: +* Net syntax:: +* Netlist syntax:: +* Pad syntax:: +* PCB syntax:: +* Pin syntax:: +* PolyArea syntax:: +* Polygon syntax:: +* Rat syntax:: +* Styles syntax:: +* Symbol syntax:: +* SymbolLine syntax:: +* Text syntax:: +* Thermal syntax:: +* Via syntax:: +@end menu +@c pcbfile Arc +@node Arc syntax +@subsection Arc +@c ./../src/parse_y.y 660 + +@cartouche +@format +Arc [X Y Width Height Thickness Clearance StartAngle DeltaAngle SFlags] +Arc (X Y Width Height Thickness Clearance StartAngle DeltaAngle NFlags) +Arc (X Y Width Height Thickness StartAngle DeltaAngle NFlags) +@end format +@end cartouche + +@table @var +@item X Y +Coordinates of the center of the arc. +@item Width Height +The width and height, from the center to the edge. The bounds of the +circle of which this arc is a segment, is thus @math{2*Width} by +@math{2*Height}. +@item Thickness +The width of the copper trace which forms the arc. +@item Clearance +The amount of space cleared around the arc when the line passes +through a polygon. The clearance is added to the thickness to get the +thickness of the clear; thus the space between the arc and the polygon +is @math{Clearance/2} wide. +@item StartAngle +The angle of one end of the arc, in degrees. In PCB, an angle of zero +points left (negative X direction), and 90 degrees points down +(positive Y direction). +@item DeltaAngle +The sweep of the arc. This may be negative. Positive angles sweep +counterclockwise. +@item SFlags +Symbolic or numeric flags. +@item NFlags +Numeric flags. +@end table + +@c pcbfile Attribute +@node Attribute syntax +@subsection Attribute +@c ./../src/parse_y.y 1268 + +@cartouche +@format +Attribute ("Name" "Value") +@end format +@end cartouche + +Attributes allow boards and elements to have arbitrary data attached +to them, which is not directly used by PCB itself but may be of use by +other programs or users. + +@table @var +@item Name +The name of the attribute + +@item Value +The value of the attribute. Values are always stored as strings, even +if the value is interpreted as, for example, a number. + +@end table + +@c pcbfile Connect +@node Connect syntax +@subsection Connect +@c ./../src/parse_y.y 1258 + +@cartouche +@format +Connect ("PinPad") +@end format +@end cartouche + +@table @var +@item PinPad +The name of a pin or pad which is included in this net. Pin and Pad +names are named by the refdes and pin name, like @code{"U14-7"} for +pin 7 of U14, or @code{"T4-E"} for pin E of T4. +@end table + +@c pcbfile Cursor +@node Cursor syntax +@subsection Cursor +@c ./../src/parse_y.y 335 + +@cartouche +@format +Cursor [X Y Zoom] +Cursor (X Y Zoom) +@end format +@end cartouche + +@table @var +@item X Y +Location of the cursor when the board was saved. +@item Zoom +The current zoom factor. Note that a zoom factor of "0" means 1 mil +per screen pixel, N means @math{2^N} mils per screen pixel, etc. The +first variant accepts floating point numbers. The special value +"1000" means "zoom to fit" +@end table + +@c pcbfile DRC +@node DRC syntax +@subsection DRC +@c ./../src/parse_y.y 376 + +@cartouche +@format +DRC [Bloat Shrink Line Silk Drill Ring] +DRC [Bloat Shrink Line Silk] +DRC [Bloat Shrink Line] +@end format +@end cartouche + +@table @var +@item Bloat +Minimum spacing between copper. +@item Shrink +Minimum copper overlap to guarantee connectivity. +@item Line +Minimum line thickness. +@item Silk +Minimum silk thickness. +@item Drill +Minimum drill size. +@item Ring +Minimum width of the annular ring around pins and vias. +@end table + +@c pcbfile Element +@node Element syntax +@subsection Element +@c ./../src/parse_y.y 816 + +@cartouche +@format +Element [SFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TSFlags] ( +Element (NFlags "Desc" "Name" "Value" MX MY TX TY TDir TScale TNFlags) ( +Element (NFlags "Desc" "Name" "Value" TX TY TDir TScale TNFlags) ( +Element (NFlags "Desc" "Name" TX TY TDir TScale TNFlags) ( +Element ("Desc" "Name" TX TY TDir TScale TNFlags) ( +@ @ @ @dots{} contents @dots{} +) +@end format +@end cartouche + +@table @var +@item SFlags +Symbolic or numeric flags, for the element as a whole. +@item NFlags +Numeric flags, for the element as a whole. +@item Desc +The description of the element. This is one of the three strings +which can be displayed on the screen. +@item Name +The name of the element, usually the reference designator. +@item Value +The value of the element. +@item MX MY +The location of the element's mark. This is the reference point +for placing the element and its pins and pads. +@item TX TY +The upper left corner of the text (one of the three strings). +@item TDir +The relative direction of the text. 0 means left to right for +an unrotated element, 1 means up, 2 left, 3 down. +@item TScale +Size of the text, as a percentage of the ``default'' size of of the +font (the default font is about 40 mils high). Default is 100 (40 +mils). +@item TSFlags +Symbolic or numeric flags, for the text. +@item TNFlags +Numeric flags, for the text. +@end table + +Elements may contain pins, pads, element lines, element arcs, +attributes, and (for older elements) an optional mark. Note that +element definitions that have the mark coordinates in the element +line, only support pins and pads which use relative coordinates. The +pin and pad coordinates are relative to the mark. Element definitions +which do not include the mark coordinates in the element line, may +have a Mark definition in their contents, and only use pin and pad +definitions which use absolute coordinates. + +@c pcbfile ElementArc +@node ElementArc syntax +@subsection ElementArc +@c ./../src/parse_y.y 927 + +@cartouche +@format +ElementArc [X Y Width Height StartAngle DeltaAngle Thickness] +ElementArc (X Y Width Height StartAngle DeltaAngle Thickness) +@end format +@end cartouche + +@table @var +@item X Y +Coordinates of the center of the arc. These are relative to the +Element's mark point for new element formats, or absolute for older +formats. +@item Width Height +The width and height, from the center to the edge. The bounds of the +circle of which this arc is a segment, is thus @math{2*Width} by +@math{2*Height}. +@item StartAngle +The angle of one end of the arc, in degrees. In PCB, an angle of zero +points left (negative X direction), and 90 degrees points down +(positive Y direction). +@item DeltaAngle +The sweep of the arc. This may be negative. Positive angles sweep +counterclockwise. +@item Thickness +The width of the silk line which forms the arc. +@end table + +@c pcbfile ElementLine +@node ElementLine syntax +@subsection ElementLine +@c ./../src/parse_y.y 925 + +@cartouche +@format +ElementLine [X1 Y1 X2 Y2 Thickness] +ElementLine (X1 Y1 X2 Y2 Thickness) +@end format +@end cartouche + +@table @var +@item X1 Y1 X2 Y2 +Coordinates of the endpoints of the line. These are relative to the +Element's mark point for new element formats, or absolute for older +formats. +@item Thickness +The width of the silk for this line. +@end table + +@c pcbfile FileVersion +@node FileVersion syntax +@subsection FileVersion +@c ./../src/parse_y.y 258 + +@cartouche +@format +FileVersion[Version] +@end format +@end cartouche + +@table @var +@item Version +File format version. This version number represents the date when the pcb file +format was last changed. +@end table + +Any version of pcb build from sources equal to or newer +than this number should be able to read the file. If this line is not present +in the input file then file format compatibility is not checked. + + +@c pcbfile Flags +@node Flags syntax +@subsection Flags +@c ./../src/parse_y.y 418 + +@cartouche +@format +Flags(Number) +@end format +@end cartouche + +@table @var +@item Number +A number, whose value is normally given in hex, individual bits of which +represent pcb-wide flags as defined in @ref{PCBFlags}. + +@end table + +@c pcbfile Grid +@node Grid syntax +@subsection Grid +@c ./../src/parse_y.y 294 + +@cartouche +@format +Grid [Step OffsetX OffsetY Visible] +Grid (Step OffsetX OffsetY Visible) +Grid (Step OffsetX OffsetY) +@end format +@end cartouche + +@table @var +@item Step +Distance from one grid point to adjacent points. This value may be a +floating point number for the first two variants. +@item OffsetX OffsetY +The "origin" of the grid. Normally zero. +@item Visible +If non-zero, the grid will be visible on the screen. +@end table + +@c pcbfile Groups +@node Groups syntax +@subsection Groups +@c ./../src/parse_y.y 432 + +@cartouche +@format +Groups("String") +@end format +@end cartouche + +@table @var +@item String + +Encodes the layer grouping information. Each group is separated by a +colon, each member of each group is separated by a comma. Group +members are either numbers from @code{1}..@var{N} for each layer, and +the letters @code{c} or @code{s} representing the component side and +solder side of the board. Including @code{c} or @code{s} marks that +group as being the top or bottom side of the board. + +@example +Groups("1,2,c:3:4:5,6,s:7,8") +@end example + +@end table + +@c pcbfile Layer +@node Layer syntax +@subsection Layer +@c ./../src/parse_y.y 573 + +@cartouche +@format +Layer (LayerNum "Name") ( +@ @ @ @dots{} contents @dots{} +) +@end format +@end cartouche + +@table @var +@item LayerNum +The layer number. Layers are numbered sequentially, starting with 1. +The last two layers (9 and 10 by default) are solder-side silk and +component-side silk, in that order. +@item Name +The layer name. +@item contents +The contents of the layer, which may include attributes, lines, arcs, rectangles, +text, and polygons. +@end table + +@c pcbfile Line +@node Line syntax +@subsection Line +@c ./../src/parse_y.y 629 + +@cartouche +@format +Line [X1 Y1 X2 Y2 Thickness Clearance SFlags] +Line (X1 Y1 X2 Y2 Thickness Clearance NFlags) +Line (X1 Y1 X2 Y2 Thickness NFlags) +@end format +@end cartouche + +@table @var +@item X1 Y1 X2 Y2 +The end points of the line +@item Thickness +The width of the line +@item Clearance +The amount of space cleared around the line when the line passes +through a polygon. The clearance is added to the thickness to get the +thickness of the clear; thus the space between the line and the +polygon is @math{Clearance/2} wide. +@item SFlags +Symbolic or numeric flags +@item NFlags +Numeric flags. +@end table + +@c pcbfile Mark +@node Mark syntax +@subsection Mark +@c ./../src/parse_y.y 929 + +@cartouche +@format +Mark [X Y] +Mark (X Y) +@end format +@end cartouche + +@table @var +@item X Y +Coordinates of the Mark, for older element formats that don't have +the mark as part of the Element line. +@end table + +@c pcbfile Net +@node Net syntax +@subsection Net +@c ./../src/parse_y.y 1235 + +@cartouche +@format +Net ("Name" "Style") ( +@ @ @ @dots{} connects @dots{} +) +@end format +@end cartouche + +@table @var +@item Name +The name of this net. +@item Style +The routing style that should be used when autorouting this net. +@end table + +@c pcbfile Netlist +@node Netlist syntax +@subsection Netlist +@c ./../src/parse_y.y 1214 + +@cartouche +@format +Netlist ( ) ( +@ @ @ @dots{} nets @dots{} +) +@end format +@end cartouche + +@c pcbfile Pad +@node Pad syntax +@subsection Pad +@c ./../src/parse_y.y 1086 + +@cartouche +@format +Pad [rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" SFlags] +Pad (rX1 rY1 rX2 rY2 Thickness Clearance Mask "Name" "Number" NFlags) +Pad (aX1 aY1 aX2 aY2 Thickness "Name" "Number" NFlags) +Pad (aX1 aY1 aX2 aY2 Thickness "Name" NFlags) +@end format +@end cartouche + +@table @var +@item rX1 rY1 rX2 rY2 +Coordinates of the endpoints of the pad, relative to the element's +mark. Note that the copper extends beyond these coordinates by half +the thickness. To make a square or round pad, specify the same +coordinate twice. +@item aX1 aY1 aX2 aY2 +Same, but absolute coordinates of the endpoints of the pad. +@item Thickness +width of the pad. +@item Clearance +add to thickness to get clearance width. +@item Mask +width of solder mask opening. +@item Name +name of pin +@item Number +number of pin +@item SFlags +symbolic or numerical flags +@item NFlags +numerical flags only +@end table + +@c pcbfile PCB +@node PCB syntax +@subsection PCB +@c ./../src/parse_y.y 271 + +@cartouche +@format +PCB ["Name" Width Height] +PCB ("Name" Width Height] +PCB ("Name") +@end format +@end cartouche + +@table @var +@item Name +Name of the PCB project +@item Width Height +Size of the board +@end table + +If you don't specify the size of the board, a very large default is +chosen. + +@c pcbfile Pin +@node Pin syntax +@subsection Pin +@c ./../src/parse_y.y 1013 + +@cartouche +@format +Pin [rX rY Thickness Clearance Mask Drill "Name" "Number" SFlags] +Pin (rX rY Thickness Clearance Mask Drill "Name" "Number" NFlags) +Pin (aX aY Thickness Drill "Name" "Number" NFlags) +Pin (aX aY Thickness Drill "Name" NFlags) +Pin (aX aY Thickness "Name" NFlags) +@end format +@end cartouche + +@table @var +@item rX rY +coordinates of center, relative to the element's mark +@item aX aY +absolute coordinates of center. +@item Thickness +outer diameter of copper annulus +@item Clearance +add to thickness to get clearance diameter +@item Mask +diameter of solder mask opening +@item Drill +diameter of drill +@item Name +name of pin +@item Number +number of pin +@item SFlags +symbolic or numerical flags +@item NFlags +numerical flags only +@end table + +@c pcbfile PolyArea +@node PolyArea syntax +@subsection PolyArea +@c ./../src/parse_y.y 353 + +@cartouche +@format +PolyArea [Area] +@end format +@end cartouche + +@table @var +@item Area +Minimum area of polygon island to retain. If a polygon has clearances that cause an isolated island to be created, then will only be retained if the area exceeds this minimum area. +@end table + +@c pcbfile Polygon +@node Polygon syntax +@subsection Polygon +@c ./../src/parse_y.y 743 + +@cartouche +@format +Polygon (SFlags) ( +@ @ @ @dots{} (X Y) @dots{} +@ @ @ @dots{} [X Y] @dots{} +@ @ @ Hole ( +@ @ @ @ @ @ @dots{} (X Y) @dots{} +@ @ @ @ @ @ @dots{} [X Y] @dots{} +@ @ @ ) +@ @ @ @dots{} +) +@end format +@end cartouche + +@table @var +@item SFlags +Symbolic or numeric flags. +@item X Y +Coordinates of each vertex. You must list at least three coordinates. +@item Hole (...) +Defines a hole within the polygon's outer contour. There may be zero or more such sections. +@end table + +@c pcbfile Rat +@node Rat syntax +@subsection Rat +@c ./../src/parse_y.y 558 + +@cartouche +@format +Rat [X1 Y1 Group1 X2 Y2 Group2 SFlags] +Rat (X1 Y1 Group1 X2 Y2 Group2 NFlags) +@end format +@end cartouche + +@table @var +@item X1 Y1 X2 Y2 +The endpoints of the rat line. +@item Group1 Group2 +The layer group each end is connected on. +@item SFlags +Symbolic or numeric flags. +@item NFlags +Numeric flags. +@end table + +@c pcbfile Styles +@node Styles syntax +@subsection Styles +@c ./../src/parse_y.y 442 + +@cartouche +@format +Styles("String") +@end format +@end cartouche + +@table @var +@item String + +Encodes the four routing styles @code{pcb} knows about. The four styles +are separated by colons. Each style consists of five parameters as follows: + +@table @var +@item Name +The name of the style. +@item Thickness +Width of lines and arcs. +@item Diameter +Copper diameter of pins and vias. +@item Drill +Drill diameter of pins and vias. +@item Keepaway +Minimum spacing to other nets. If omitted, 10 mils is the default. + +@end table + +@end table + +@example +Styles("Signal,10,40,20:Power,25,60,35:Fat,40,60,35:Skinny,8,36,20") +Styles["Logic,1000,3600,2000,1000:Power,2500,6000,3500,1000: +@ @ @ Line,4000,6000,3500,1000:Breakout,600,2402,1181,600"] +@end example + +@noindent +Note that strings in actual files cannot span lines; the above example +is split across lines only to make it readable. + +@c pcbfile Symbol +@node Symbol syntax +@subsection Symbol +@c ./../src/parse_y.y 1148 + +@cartouche +@format +Symbol [Char Delta] ( +Symbol (Char Delta) ( +@ @ @ @dots{} symbol lines @dots{} +) +@end format +@end cartouche + +@table @var +@item Char +The character or numerical character value this symbol represents. +Characters must be in single quotes. +@item Delta +Additional space to allow after this character. +@end table + +@c pcbfile SymbolLine +@node SymbolLine syntax +@subsection SymbolLine +@c ./../src/parse_y.y 1197 + +@cartouche +@format +SymbolLine [X1 Y1 X2 Y1 Thickness] +SymbolLine (X1 Y1 X2 Y1 Thickness) +@end format +@end cartouche + +@table @var +@item X1 Y1 X2 Y2 +The endpoints of this line. +@item Thickness +The width of this line. +@end table + +@c pcbfile Text +@node Text syntax +@subsection Text +@c ./../src/parse_y.y 689 + +@cartouche +@format +Text [X Y Direction Scale "String" SFlags] +Text (X Y Direction Scale "String" NFlags) +Text (X Y Direction "String" NFlags) +@end format +@end cartouche + +@table @var +@item X Y +The location of the upper left corner of the text. +@item Direction +0 means text is drawn left to right, 1 means up, 2 means right to left +(i.e. upside down), and 3 means down. +@item Scale +Size of the text, as a percentage of the ``default'' size of of the +font (the default font is about 40 mils high). Default is 100 (40 +mils). +@item String +The string to draw. +@item SFlags +Symbolic or numeric flags. +@item NFlags +Numeric flags. +@end table + +@c pcbfile Thermal +@node Thermal syntax +@subsection Thermal +@c ./../src/parse_y.y 365 + +@cartouche +@format +Thermal [Scale] +@end format +@end cartouche + +@table @var +@item Scale +Relative size of thermal fingers. A value of 1.0 makes the finger +width twice the clearance gap width (measured across the gap, not +diameter). The normal value is 0.5, which results in a finger width +the same as the clearance gap width. +@end table + +@c pcbfile Via +@node Via syntax +@subsection Via +@c ./../src/parse_y.y 498 + +@cartouche +@format +Via [X Y Thickness Clearance Mask Drill "Name" SFlags] +Via (X Y Thickness Clearance Mask Drill "Name" NFlags) +Via (X Y Thickness Clearance Drill "Name" NFlags) +Via (X Y Thickness Drill "Name" NFlags) +Via (X Y Thickness "Name" NFlags) +@end format +@end cartouche + +@table @var +@item X Y +coordinates of center +@item Thickness +outer diameter of copper annulus +@item Clearance +add to thickness to get clearance diameter +@item Mask +diameter of solder mask opening +@item Drill +diameter of drill +@item Name +string, name of via (vias have names?) +@item SFlags +symbolic or numerical flags +@item NFlags +numerical flags only +@end table + +@c pcbfile ~objectflags +@c ./../src/const.h 110 +@node Object Flags +@section Object Flags + +Note that object flags can be given numerically (like @code{0x0147}) +or symbolically (like @code{"found,showname,square"}. Some numeric +values are reused for different object types. The table below lists +the numeric value followed by the symbolic name. + +@table @code +@item 0x0001 pin +If set, this object is a pin. This flag is for internal use only. +@item 0x0002 via +Likewise, for vias. +@item 0x0004 found +If set, this object has been found by @code{FindConnection()}. +@item 0x0008 hole +For pins and vias, this flag means that the pin or via is a hole +without a copper annulus. +@item 0x0010 rat +If set for a line, indicates that this line is a rat line instead of a +copper trace. +@item 0x0010 pininpoly +For pins and pads, this flag is used internally to indicate that the +pin or pad overlaps a polygon on some layer. +@item 0x0010 clearpoly +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. +@item 0x0010 hidename +For elements, when set the name of the element is hidden. +@item 0x0020 showname +For elements, when set the names of pins are shown. +@item 0x0020 clearline +For lines and arcs, the line/arc will clear polygons instead of +connecting to them. +@item 0x0020 fullpoly +For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one). +@item 0x0040 selected +Set when the object is selected. +@item 0x0080 onsolder +For elements and pads, indicates that they are on the solder side. +@item 0x0080 auto +For lines and vias, indicates that these were created by the +autorouter. +@item 0x0100 square +For pins and pads, indicates a square (vs round) pin/pad. +@item 0x0200 rubberend +For lines, used internally for rubber band moves. +@item 0x0200 warn +For pins, vias, and pads, set to indicate a warning. +@item 0x0400 usetherm +Obsolete, indicates that pins/vias should be drawn with thermal +fingers. +@item 0x0400 +Obsolete, old files used this to indicate lines drawn on silk. +@item 0x0800 octagon +Draw pins and vias as octagons. +@item 0x1000 drc +Set for objects that fail DRC. +@item 0x2000 lock +Set for locked objects. +@item 0x4000 edge2 +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. +@item 0x8000 marker +Marker used internally to avoid revisiting an object. +@item 0x10000 nopaste +For pads, set to prevent a solderpaste stencil opening for the +pad. Primarily used for pads used as fiducials. +@end table +@c pcbfile ~pcbflags +@c ./../src/const.h 149 +@node PCBFlags +@section PCBFlags +@table @code +@item 0x00001 +Pinout displays pin numbers instead of pin names. +@item 0x00002 +Use local reference for moves, by setting the mark at the beginning of +each move. +@item 0x00004 +When set, only polygons and their clearances are drawn, to see if +polygons have isolated regions. +@item 0x00008 +Display DRC region on crosshair. +@item 0x00010 +Do all move, mirror, rotate with rubberband connections. +@item 0x00020 +Display descriptions of elements, instead of refdes. +@item 0x00040 +Display names of elements, instead of refdes. +@item 0x00080 +Auto-DRC flag. When set, PCB doesn't let you place copper that +violates DRC. +@item 0x00100 +Enable 'all-direction' lines. +@item 0x00200 +Switch starting angle after each click. +@item 0x00400 +Force unique names on board. +@item 0x00800 +New lines/arc clear polygons. +@item 0x01000 +Crosshair snaps to pins and pads. +@item 0x02000 +Show the solder mask layer. +@item 0x04000 +Draw with thin lines. +@item 0x08000 +Move items orthogonally. +@item 0x10000 +Draw autoroute paths real-time. +@item 0x20000 +New polygons are full ones. +@item 0x40000 +Names are locked, the mouse cannot select them. +@item 0x80000 +Everything but names are locked, the mouse cannot select anything else. +@item 0x100000 +New polygons are full polygons. +@item 0x200000 +When set, element names are not drawn. +@end table Index: tags/1.2.7/doc-orig/puller.pcb =================================================================== --- tags/1.2.7/doc-orig/puller.pcb (nonexistent) +++ tags/1.2.7/doc-orig/puller.pcb (revision 13657) @@ -0,0 +1,848 @@ +# release: pcb 1.99s + +PCB["" 110000 30000] + +Grid[10000.00000000 0 0 1] +Cursor[0 0 0.000000] +Thermal[0.500000] +DRC[1000 1000 1000 1000 1500 1000] +Flags(0x0000000000001c40) +Groups("1,c:2,s:3:4:5:6:7:8") +Styles["Signal,1000,3600,2000,1000:Power,2500,6000,3500,1000:Fat,5000,10000,5000,1000:Skinny,600,2402,1181,600"] + +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[500 5000 1500 5000 800] + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[0 2000 1000 1000 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[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2500 3000 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 3000 2000 3500 800] + SymbolLine[0 3000 1500 3000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[0 5000 2500 2500 800] + SymbolLine[2500 1000 2500 2500 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + 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[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2500 800] + SymbolLine[1500 3000 2000 2500 800] +) +Symbol['9' 1200] +( + SymbolLine[0 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 1500 0 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 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 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[500 3000 2000 3000 800] + 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] +) +Symbol['C' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 3000 1500 3000 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 3000 1500 3000 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[0 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] +) +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 2500 800] + SymbolLine[1500 2500 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 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 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 4000 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[500 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 1000 2000 4000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 1500 3500 800] + SymbolLine[1500 3500 3000 5000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 800] + SymbolLine[2500 4000 2500 5000 800] + SymbolLine[0 4000 0 5000 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[2500 1000 2500 1500 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 1000 2500 800] + SymbolLine[1000 2500 2000 1500 800] + SymbolLine[2000 1000 2000 1500 800] + SymbolLine[1000 2500 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[2500 1000 2500 1500 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[0 4000 0 5000 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 2500 800] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2500 800] + 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 3000 2000 4000 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] +) +Via[30000 20000 10000 2000 0 5000 "" ""] +Via[80000 20000 10000 2000 0 5000 "" ""] +Layer(1 "component") +( + Line[10000 20000 20000 20000 2000 2000 "clearline"] + Line[40000 20000 50000 20000 2000 2000 "clearline"] + Line[60000 20000 70000 20000 2000 2000 "clearline"] + Line[100000 20000 84848 11254 2000 2000 "clearline"] + Arc[30000 20000 10000 10000 2000 2000 270 -90 "clearline"] + Arc[30000 20000 10000 10000 2000 2000 270 90 "clearline"] + Arc[80000 20000 10000 10000 2000 2000 270 -29 "clearline"] + Arc[80000 20000 10000 10000 2000 2000 270 90 "clearline"] +) +Layer(2 "solder") +( +) +Layer(3 "GND") +( +) +Layer(4 "power") +( +) +Layer(5 "signal1") +( +) +Layer(6 "signal2") +( +) +Layer(7 "signal3") +( +) +Layer(8 "signal4") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[33000 20000 38000 20000 500 2000 "clearline"] + Line[40000 13000 40000 18000 500 2000 "clearline"] + Line[42000 20000 47000 20000 500 2000 "clearline"] + Line[40000 22000 40000 27000 500 2000 "clearline"] + Line[77848 11254 82848 11254 500 2000 "clearline"] + Line[84848 4254 84848 9254 500 2000 "clearline"] + Line[86848 11254 91848 11254 500 2000 "clearline"] + Line[84848 13254 84848 18254 500 2000 "clearline"] + Arc[40000 20000 2000 2000 500 2000 0 -90 "clearline"] + Arc[39999 20001 2001 2001 500 2000 270 -90 "clearline"] + Arc[40002 20002 1998 1998 500 2000 180 -90 "clearline"] + Arc[40002 19998 2002 2002 500 2000 90 -90 "clearline"] + Arc[84848 11254 2000 2000 500 2000 0 -90 "clearline"] + Arc[84847 11255 2001 2001 500 2000 270 -90 "clearline"] + Arc[84850 11256 1998 1998 500 2000 180 -90 "clearline"] + Arc[84850 11252 2002 2002 500 2000 90 -90 "clearline"] +) Index: tags/1.2.7/doc-orig/puller.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/puller.pdf =================================================================== --- tags/1.2.7/doc-orig/puller.pdf (nonexistent) +++ tags/1.2.7/doc-orig/puller.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/puller.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/puller.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/puller.png =================================================================== --- tags/1.2.7/doc-orig/puller.png (nonexistent) +++ tags/1.2.7/doc-orig/puller.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/puller.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/refcard.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/refcard.pdf =================================================================== --- tags/1.2.7/doc-orig/refcard.pdf (nonexistent) +++ tags/1.2.7/doc-orig/refcard.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/refcard.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/refcard.tex =================================================================== --- tags/1.2.7/doc-orig/refcard.tex (nonexistent) +++ tags/1.2.7/doc-orig/refcard.tex (revision 13657) @@ -0,0 +1,258 @@ +% $Id$ +% +% COPYRIGHT +% +% PCB, interactive printed circuit board design +% Copyright (C) 1994, 1995 Thomas Nau +% Copyright (C) 1998, 1999, 2000, 2001 harry eaton +% Copyright (C) 2009 Chitlesh Goorah +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +% +% Contact addresses for paper mail and Email: +% Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany +% Thomas.Nau@rz.uni-ulm.de + + +\documentclass[11pt,landscape]{article} +\usepackage{multicol} +\usepackage{calc} +\usepackage{ifthen} +\usepackage[landscape,left=2.5cm,top=2cm,right=2cm,bottom=2cm,nohead]{geometry} + +% Turn off header and footer +\pagestyle{empty} + +% Redefine section commands to use less space +\makeatletter +\renewcommand{\section}{\@startsection{section}{1}{0mm}% + {-1ex plus -.5ex minus -.2ex}% + {0.5ex plus .2ex}%x + {\normalfont\large\bfseries}} +\renewcommand{\subsection}{\@startsection{subsection}{2}{0mm}% + {-1explus -.5ex minus -.2ex}% + {0.5ex plus .2ex}% + {\normalfont\normalsize\bfseries}} +\renewcommand{\subsubsection}{\@startsection{subsubsection}{3}{0mm}% + {-1ex plus -.5ex minus -.2ex}% + {1ex plus .2ex}% + {\normalfont\small\bfseries}} +\makeatother + +% Define BibTeX command +\def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em + T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}} + +% Don't print section numbers +\setcounter{secnumdepth}{0} + + +\setlength{\parindent}{0pt} +\setlength{\parskip}{0pt plus 0.5ex} + +%------------------------------------------------------------------ +% some new commands to define the modifier keys +% +\newcommand{\Shift}{{\it [S]}} +\newcommand{\Ctrl}{{\it [C]}} +\newcommand{\Mod}{{\it [M]}} +\newcommand{\Btn}{{\it Btn}} +\newcommand{\Fun}{{\it F}} + +\begin{document} +\raggedright +\footnotesize +\begin{multicols}{3} + + +% multicol parameters +% These lengths are set only within the two main columns +%\setlength{\columnseprule}{0.25pt} +\setlength{\premulticols}{1pt} +\setlength{\postmulticols}{1pt} +\setlength{\multicolsep}{1pt} +\setlength{\columnsep}{2pt} + +\begin{center} + \Large{\textbf{PCB Command reference}} + \footnote{http://pcb.gpleda.org/index.html} + \footnote{Obviously \Shift, \Ctrl, \Mod, \Fun \space and \Btn \space mean the shift, + control, modifier1 (BTNMOD for buttons), function key and mouse button.} \\ +\end{center} + +\section{Misc operations} +\begin{tabular}{@{}ll@{}} +backspace & remove object \\ +\Shift\Ctrl\Btn1 & remove object \\ +scroll wheel & vertical pan \\ +\Shift scroll wheel & horizontal pan \\ +\Btn1 & current mode action\\ +u & undo operation \\ +\Shift r & redo operation \\ +\Shift\Ctrl u & clear undo-list \\ +tab & switch viewing side \\ +cursor key & move crosshair 1 grid\\ +\Shift cursor key! & move crosshair 10 grid\\ +\end{tabular} + + +\section{Connections} +\begin{tabular}{@{}ll@{}} +\Shift f & reset found connections \\ +f & find connections \\ +\Shift backspace & remove connections \\ +\end{tabular} + + +\section{User (:) commands} +\begin{tabular}{@{}ll@{}} +:DRC() & check layout for rule violations \\ +:l [file] & load data file \\ +:le [file] & load element to buffer \\ +:m [file] & load layout to buffer \\ +:q & quit application \\ +:rn [file] & load netlist \\ +:s [file] & save data as file \\ +\end{tabular} + +\section{Display} +\begin{tabular}{@{}ll@{}} +c & center display \\ +g & increase grid spacing \\ +\Shift g & decrease grid spacing \\ +\Ctrl m & mark location \\ +r & clear and redraw output \\ +z & zoom in \\ +\Shift z & zoom out \\ +v & zoom extents \\ +\Shift\Btn3 & temporary zoom extents \\ +\end{tabular} + + +\section{Selections} +\begin{tabular}{@{}ll@{}} +\Btn2 & select/deselect object \\ +\Shift\Btn2 & toggle object to selection \\ +drag \Btn2 & select only objects in box \\ +drag \Shift\Btn2 & add box to selection \\ +\Shift m & move selected to current layer \\ +\end{tabular} + + +\section{Copy and move} +\begin{tabular}{@{}ll@{}} +drag \Btn2 & move object or selection\\ +drag \Mod\Btn2 & copy object \\ +drag \Shift\Mod\Btn2 & override rubberband \& move \\ +m & move to current layer \\ +\end{tabular} + + +\section{Pastebuffer} +\begin{tabular}{@{}ll@{}} +\Ctrl x & copy selected objects to buffer \\ + & and enter pastebuffer mode \\ +\Shift \Ctrl x & cut selected objects to buffer \\ + & and enter pastebuffer mode \\ +\Btn1 & in pastebuffer mode copy to layout \\ +\Shift \Fun7 & rotate 90 degree cc \\ +\Ctrl 1$\cdots$5 & select buffer \# 1$\cdots$5 \\ +\end{tabular} + + +\section{Sizing} +\begin{tabular}{@{}ll@{}} +s & increase size of TLAPV\footnotemark\\ +\Shift s & decrease size of TLAPV\\ +\Mod s & increase drill size of PV \\ +\Shift\Mod s & decrease drill size of PV \\ +k & increase clearance of LAPV\\ +\Shift\ k & decrease clearance of LAPV\\ +\end{tabular} +\footnotetext{TLAPV: text, line, arc, pin or via} + + +\section{Element} +\begin{tabular}{@{}ll@{}} +d & display pinout \\ +\Shift d & open pinout window \\ +h & hide/show element name \\ +n & change element name \\ +\end{tabular} + + +\section{Pin/pad} +\begin{tabular}{@{}ll@{}} +n & change name \\ +q & toggle square flag \\ +\end{tabular} + + +\section{Via} +\begin{tabular}{@{}ll@{}} +\Fun1 & enter via-mode \\ +\Ctrl v & increase initial size \\ +\Shift \Ctrl v & decrease initial size \\ +\Mod v & inc. initial drilling hole \\ +\Shift\Mod v & dec. initial drilling hole \\ +\Ctrl h & convert via to mounting hole \\ +\end{tabular} + + +\section{Lines and arcs} +\begin{tabular}{@{}ll@{}} +\Fun2 & enter line mode \\ +\Fun3 & enter arc mode \\ +l & increase initial line size \\ +\Shift l & decrease initial line size \\ +period & toggle 45 degree enforcement \\ +/ & cycle multiline mode \\ +\Shift & override multiline mode \\ +\end{tabular} + + +\section{Polygon} +\begin{tabular}{@{}ll@{}} +\Fun5 & enter rectangle-mode \\ +\Fun6 & enter polygon-mode \\ +\Shift p & close path \\ +insert & enter insert point mode \\ +\end{tabular} + + +\section{Text} +\begin{tabular}{@{}ll@{}} +\Fun4 & enter text-mode \\ +n & edit string \\ +t & increase initial text size \\ +\Shift t & decrease initial text size \\ +\end{tabular} + + +\section{Rats nest} +\begin{tabular}{@{}ll@{}} +w & add all rats \\ +\Shift w & add rats to selected pins/pads \\ +e & delete all rats \\ +\Shift e & delete selected rats \\ +o & optimize all rats \\ +\Shift o & optimize selected rats \\ +\end{tabular} + + +\end{multicols} + + +\end{document} Index: tags/1.2.7/doc-orig/thermal.pcb =================================================================== --- tags/1.2.7/doc-orig/thermal.pcb (nonexistent) +++ tags/1.2.7/doc-orig/thermal.pcb (revision 13657) @@ -0,0 +1,844 @@ +# release: pcb-bin 1.99q + +PCB["thermal" 300000 300000] + +Grid[5000.00000000 0 0 1] +Cursor[88600 72400 2.000000] +Thermal[0.500000] +DRC[699 400 800 800 1000 750] +Flags(0x0000000000000840) +Groups("1,s:2,c:3:4:5:6:7:8") +Styles["Signal,2500,30000,10000,0:Power,2500,6000,3500,1000:Fat,4000,6000,3500,1000:Skinny,200,2402,1181,600"] + +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[500 5000 1500 5000 800] + SymbolLine[1000 1000 1000 5000 800] + SymbolLine[0 2000 1000 1000 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[2000 1500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[500 3000 2000 3000 800] +) +Symbol['4' 1200] +( + SymbolLine[0 3000 2000 1000 800] + SymbolLine[0 3000 2500 3000 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 3000 2000 3500 800] + SymbolLine[0 3000 1500 3000 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[2000 3500 2000 4500 800] +) +Symbol['7' 1200] +( + SymbolLine[0 5000 2500 2500 800] + SymbolLine[2500 1000 2500 2500 800] + SymbolLine[0 1000 2500 1000 800] +) +Symbol['8' 1200] +( + 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[2000 3500 2000 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 2500 500 3000 800] + SymbolLine[0 1500 0 2500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 1500 1000 800] + SymbolLine[1500 1000 2000 1500 800] + SymbolLine[2000 1500 2000 2500 800] + SymbolLine[1500 3000 2000 2500 800] +) +Symbol['9' 1200] +( + SymbolLine[0 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 1500 0 5000 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 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 3500 2500 4500 800] + SymbolLine[2000 3000 2500 3500 800] + SymbolLine[500 3000 2000 3000 800] + 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] +) +Symbol['C' 1200] +( + SymbolLine[500 5000 2000 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[0 1500 0 4500 800] + SymbolLine[0 1500 500 1000 800] + SymbolLine[500 1000 2000 1000 800] +) +Symbol['D' 1200] +( + SymbolLine[500 1000 500 5000 800] + SymbolLine[2000 1000 2500 1500 800] + SymbolLine[2500 1500 2500 4500 800] + SymbolLine[2000 5000 2500 4500 800] + SymbolLine[0 5000 2000 5000 800] + SymbolLine[0 1000 2000 1000 800] +) +Symbol['E' 1200] +( + SymbolLine[0 3000 1500 3000 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 3000 1500 3000 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[0 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] +) +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 2500 800] + SymbolLine[1500 2500 3000 1000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['N' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 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 4500 800] + SymbolLine[1500 5000 2000 4500 800] + SymbolLine[500 5000 1500 5000 800] + SymbolLine[0 4500 500 5000 800] + SymbolLine[1000 4000 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[500 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 1000 2000 4000 800] +) +Symbol['W' 1200] +( + SymbolLine[0 1000 0 5000 800] + SymbolLine[0 5000 1500 3500 800] + SymbolLine[1500 3500 3000 5000 800] + SymbolLine[3000 1000 3000 5000 800] +) +Symbol['X' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 2500 4000 800] + SymbolLine[2500 4000 2500 5000 800] + SymbolLine[0 4000 0 5000 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[2500 1000 2500 1500 800] +) +Symbol['Y' 1200] +( + SymbolLine[0 1000 0 1500 800] + SymbolLine[0 1500 1000 2500 800] + SymbolLine[1000 2500 2000 1500 800] + SymbolLine[2000 1000 2000 1500 800] + SymbolLine[1000 2500 1000 5000 800] +) +Symbol['Z' 1200] +( + SymbolLine[0 1000 2500 1000 800] + SymbolLine[2500 1000 2500 1500 800] + SymbolLine[0 4000 2500 1500 800] + SymbolLine[0 4000 0 5000 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 2500 800] + SymbolLine[0 3500 0 5000 800] +) +Symbol['j' 1000] +( + SymbolLine[500 2000 500 2500 800] + 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 0 4000 800] + SymbolLine[0 4000 1000 5000 800] + SymbolLine[1000 5000 2000 4000 800] + SymbolLine[2000 3000 2000 4000 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] +) +Via[45000 135000 30000 10000 0 10000 "" "thermal(0S)"] +Via[255000 135000 30000 10000 0 10000 "" ""] +Via[150000 135000 30000 10000 0 10000 "" "thermal(0)"] +Layer(1 "component") +( + Polygon("clearpoly") + ( + [5000 95000] [290000 95000] [290000 175000] [5000 175000] + ) +) +Layer(2 "solder") +( +) +Layer(3 "GND") +( +) +Layer(4 "power") +( +) +Layer(5 "signal1") +( +) +Layer(6 "signal2") +( +) +Layer(7 "unused") +( +) +Layer(8 "unused") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Line[255000 180000 255000 160000 2500 10000 "clearline"] + Line[255000 160000 260000 165000 2500 10000 "clearline"] + Line[45000 160000 50000 165000 2500 10000 "clearline"] + Line[45000 160000 40000 165000 2500 10000 "clearline"] + Line[45000 180000 45000 160000 2500 10000 "clearline"] + Line[255000 160000 250000 165000 2500 10000 "clearline"] + Line[150000 160000 155000 165000 2500 10000 "clearline"] + Line[150000 160000 145000 165000 2500 10000 "clearline"] + Line[150000 180000 150000 160000 2500 10000 "clearline"] + Text[220000 190000 0 200 "no connection" ""] + Text[15000 180000 0 200 "Via/Pin with " ""] + Text[5000 190000 0 200 "solid connection " ""] + Text[225000 180000 0 200 "Via/Pin with" ""] + Text[120000 180000 0 200 "Via/Pin with " ""] + Text[130000 190000 0 200 "thermal" ""] +) Index: tags/1.2.7/doc-orig/thermal.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/thermal.pdf =================================================================== --- tags/1.2.7/doc-orig/thermal.pdf (nonexistent) +++ tags/1.2.7/doc-orig/thermal.pdf (revision 13657) Property changes on: tags/1.2.7/doc-orig/thermal.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/thermal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.7/doc-orig/thermal.png =================================================================== --- tags/1.2.7/doc-orig/thermal.png (nonexistent) +++ tags/1.2.7/doc-orig/thermal.png (revision 13657) Property changes on: tags/1.2.7/doc-orig/thermal.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.7/doc-orig/tutorial/Makefile =================================================================== --- tags/1.2.7/doc-orig/tutorial/Makefile (nonexistent) +++ tags/1.2.7/doc-orig/tutorial/Makefile (revision 13657) @@ -0,0 +1,21 @@ +# This Makefile is a plain old hand written one; all configuration settings +# are included from ../Makefile.conf which is scconfig generated + +all: + +install_: + $(MKDIR) "$(DOCDIR)/examples" + $(CPC) "`pwd`/tut1.pcb" "$(DOCDIR)/examples/tut1.pcb" + +install: + make install_ CPC="$(CP)" + +linstall: + make install_ CPC="$(LN)" + +uninstall: + $(RM) "$(DOCDIR)/examples/tut1.pcb" + +clean: + +include ../Makefile.conf Index: tags/1.2.7/doc-orig/tutorial/tut1.pcb =================================================================== --- tags/1.2.7/doc-orig/tutorial/tut1.pcb (nonexistent) +++ tags/1.2.7/doc-orig/tutorial/tut1.pcb (revision 13657) @@ -0,0 +1,2018 @@ +# release: pcb 1.9.9d.ALPHA + +PCB("" 3500 3300) + +Grid(39.37007904 18 1 1) +Cursor(766 1300 1) +Flags(0x0000000000001750) +Groups("4,5,6,c:1,2,3,s:8:7:") +Styles("Signal,10,40,20,10:Power,25,60,35,10:Fat,40,60,35,10:Skinny,8,36,20,10") + +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(5 40 15 40 8) + SymbolLine(10 0 10 40 8) + SymbolLine(0 10 10 0 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(20 5 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(5 20 20 20 8) +) +Symbol('4' 12) +( + SymbolLine(0 20 20 0 8) + SymbolLine(0 20 25 20 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 20 20 25 8) + SymbolLine(0 20 15 20 8) + SymbolLine(5 40 15 40 8) + SymbolLine(15 40 20 35 8) + SymbolLine(20 25 20 35 8) +) +Symbol('7' 12) +( + SymbolLine(0 40 25 15 8) + SymbolLine(25 0 25 15 8) + SymbolLine(0 0 25 0 8) +) +Symbol('8' 12) +( + 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(20 25 20 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 15 5 20 8) + SymbolLine(0 5 0 15 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 15 0 8) + SymbolLine(15 0 20 5 8) + SymbolLine(20 5 20 15 8) + SymbolLine(15 20 20 15 8) +) +Symbol('9' 12) +( + SymbolLine(0 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 5 0 40 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 20 0 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 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 25 25 35 8) + SymbolLine(20 20 25 25 8) + SymbolLine(5 20 20 20 8) + 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) +) +Symbol('C' 12) +( + SymbolLine(5 40 20 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(0 5 0 35 8) + SymbolLine(0 5 5 0 8) + SymbolLine(5 0 20 0 8) +) +Symbol('D' 12) +( + SymbolLine(5 0 5 40 8) + SymbolLine(20 0 25 5 8) + SymbolLine(25 5 25 35 8) + SymbolLine(20 40 25 35 8) + SymbolLine(0 40 20 40 8) + SymbolLine(0 0 20 0 8) +) +Symbol('E' 12) +( + SymbolLine(0 20 15 20 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 20 15 20 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(0 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) +) +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 15 8) + SymbolLine(15 15 30 0 8) + SymbolLine(30 0 30 40 8) +) +Symbol('N' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 0 0 5 8) + SymbolLine(0 5 25 30 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 35 8) + SymbolLine(15 40 20 35 8) + SymbolLine(5 40 15 40 8) + SymbolLine(0 35 5 40 8) + SymbolLine(10 30 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(5 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 0 30 8) + SymbolLine(0 30 10 40 8) + SymbolLine(10 40 20 30 8) + SymbolLine(20 0 20 30 8) +) +Symbol('W' 12) +( + SymbolLine(0 0 0 40 8) + SymbolLine(0 40 15 25 8) + SymbolLine(15 25 30 40 8) + SymbolLine(30 0 30 40 8) +) +Symbol('X' 12) +( + SymbolLine(0 0 0 5 8) + SymbolLine(0 5 25 30 8) + SymbolLine(25 30 25 40 8) + SymbolLine(0 30 0 40 8) + SymbolLine(0 30 25 5 8) + SymbolLine(25 0 25 5 8) +) +Symbol('Y' 12) +( + SymbolLine(0 0 0 5 8) + SymbolLine(0 5 10 15 8) + SymbolLine(10 15 20 5 8) + SymbolLine(20 0 20 5 8) + SymbolLine(10 15 10 40 8) +) +Symbol('Z' 12) +( + SymbolLine(0 0 25 0 8) + SymbolLine(25 0 25 5 8) + SymbolLine(0 30 25 5 8) + SymbolLine(0 30 0 40 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 15 8) + SymbolLine(0 25 0 40 8) +) +Symbol('j' 10) +( + SymbolLine(5 10 5 15 8) + 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 0 30 8) + SymbolLine(0 30 10 40 8) + SymbolLine(10 40 20 30 8) + SymbolLine(20 20 20 30 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) +) +Via(2075 1455 50 24 80 28 "" 0x10100002) +Via(1790 1570 50 22 80 28 "" 0x10100002) +Via(1450 1575 50 24 80 28 "" 0x10100002) +Via(2965 3005 110 30 140 110 "" 0x0000000a) +Via(465 605 110 30 140 110 "" 0x0000000a) +Via(465 3015 110 30 140 110 "" 0x0000000a) +Via(2965 595 110 30 140 110 "" 0x0000000a) +Via(1985 1300 50 30 80 28 "" 0x00000002) + +Element(0x00000000 "" "X1" "" 2330 850 444 -101 0 125 0x00000000) +( + Pin(0 0 60 30 90 28 "" "1" 0x00000001) + Pin(300 0 60 30 90 28 "" "2" 0x00000001) + Pin(300 -300 60 30 90 28 "" "3" 0x00000001) + Pin(0 -300 60 30 90 28 "" "4" 0x00000001) + ElementLine (-110 110 -110 -350 10) + ElementLine (-60 -400 350 -400 10) + ElementLine (400 -350 400 60 10) + ElementLine (350 110 -110 110 10) + ElementArc (-60 -350 50 50 270 90 10) + ElementArc (350 -350 50 50 180 90 10) + ElementArc (350 60 50 50 90 90 10) + ) + +Element(0x00000000 "RS422 Transciever" "U6" "LTC490" 1005 895 -505 -55 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "Vcc" "1" 0x00000101) + Pin(0 -100 60 30 90 28 "R" "2" 0x00000001) + Pin(0 -200 60 30 90 28 "D" "3" 0x00000001) + Pin(0 -300 60 30 90 28 "GND" "4" 0x00000001) + Pin(-300 -300 60 30 90 28 "Y" "5" 0x00000001) + Pin(-300 -200 60 30 90 28 "Z" "6" 0x00000001) + Pin(-300 -100 60 30 90 28 "B" "7" 0x00000001) + Pin(-300 0 60 30 90 28 "A" "8" 0x00000001) + ElementLine (50 50 50 -350 10) + ElementLine (50 -350 -350 -350 10) + ElementLine (-350 -350 -350 50 10) + ElementLine (50 50 -100 50 10) + ElementLine (-200 50 -350 50 10) + ElementArc (-150 50 50 50 180 180 10) + ) + +Element(0x00000000 "PIC16C54A" "U5" "PIC16C54" 1195 860 465 80 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "RA2" "1" 0x00000101) + Pin(100 0 60 30 90 28 "RA3" "2" 0x00000001) + Pin(200 0 60 30 90 28 "RTCC" "3" 0x00000001) + Pin(300 0 60 30 90 28 "/MCLR" "4" 0x00000001) + Pin(400 0 60 30 90 28 "Vss" "5" 0x00000001) + Pin(500 0 60 30 90 28 "RB0" "6" 0x00000001) + Pin(600 0 60 30 90 28 "RB1" "7" 0x00000001) + Pin(700 0 60 30 90 28 "RB2" "8" 0x00000001) + Pin(800 0 60 30 90 28 "RB3" "9" 0x00000001) + Pin(800 -300 60 30 90 28 "RB4" "10" 0x00000001) + Pin(700 -300 60 30 90 28 "RB5" "11" 0x00000001) + Pin(600 -300 60 30 90 28 "RB6" "12" 0x00000001) + Pin(500 -300 60 30 90 28 "RB7" "13" 0x00000001) + Pin(400 -300 60 30 90 28 "Vdd" "14" 0x00000001) + Pin(300 -300 60 30 90 28 "OSC2/CLKOUT" "15" 0x00000001) + Pin(200 -300 60 30 90 28 "OSC1/CLKIN" "16" 0x00000001) + Pin(100 -300 60 30 90 28 "RA0" "17" 0x00000001) + Pin(0 -300 60 30 90 28 "RA1" "18" 0x00000001) + ElementLine (-50 50 850 50 10) + ElementLine (850 50 850 -350 10) + ElementLine (850 -350 -50 -350 10) + ElementLine (-50 50 -50 -100 10) + ElementLine (-50 -200 -50 -350 10) + ElementArc (-50 -150 50 50 90 180 10) + ) + +Element(0x00000000 "SMD Cap" "C17" "" 2155 815 -90 -329 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000001) + Pin(0 -200 80 30 110 35 "2" "2" 0x00000001) + ElementLine (-50 50 50 50 10) + ElementLine (50 50 50 -250 10) + ElementLine (50 -250 -50 -250 10) + ElementLine (-50 -250 -50 50 10) + ) + +Element(0x00000000 "SMD 0805" "C13" "" 2525 1510 -30 45 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(0 -90 0 -90 60 30 90 "2" "2" 0x00000100) + ElementLine (-35 -125 -35 35 10) + ElementLine (35 -125 -35 -125 10) + ElementLine (35 35 35 -125 10) + ElementLine (-35 35 35 35 10) + ) + +Element(0x00000010 "SMD 0805" "C16" "" 1080 1355 -15 -115 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(90 0 90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (125 -35 -35 -35 10) + ElementLine (125 35 125 -35 10) + ElementLine (-35 35 125 35 10) + ElementLine (-35 -35 -35 35 10) + ) + +Element(0x00000000 "SMD 0805" "C14" "" 1175 1690 -195 20 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(0 90 0 90 60 30 90 "2" "2" 0x00000100) + ElementLine (35 125 35 -35 10) + ElementLine (-35 125 35 125 10) + ElementLine (-35 -35 -35 125 10) + ElementLine (35 -35 -35 -35 10) + ) + +Element(0x00000000 "SMD Cap" "C15" "" 1280 1785 65 -174 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000001) + Pin(0 -200 80 30 110 35 "2" "2" 0x00000001) + ElementLine (-50 50 50 50 10) + ElementLine (50 50 50 -250 10) + ElementLine (50 -250 -50 -250 10) + ElementLine (-50 -250 -50 50 10) + ) + +Element(0x00000010 "SMD 0805" "C10" "" 2095 1310 -190 -60 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(90 0 90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (125 -35 -35 -35 10) + ElementLine (125 35 125 -35 10) + ElementLine (-35 35 125 35 10) + ElementLine (-35 -35 -35 35 10) + ) + +Element(0x00000000 "SMD Cap" "C12" "" 2345 1320 -35 -129 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000001) + Pin(200 0 80 30 110 35 "2" "2" 0x00000001) + ElementLine (-50 -50 -50 50 10) + ElementLine (-50 50 250 50 10) + ElementLine (250 50 250 -50 10) + ElementLine (250 -50 -50 -50 10) + ) + +Element(0x00000000 "R 0.25W" "R13" "100" 1130 1435 230 65 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(400 0 60 30 90 28 "2" "2" 0x10000001) + ElementLine (100 -50 300 -50 10) + ElementLine (300 -50 300 50 10) + ElementLine (300 50 100 50 10) + ElementLine (100 50 100 -50 10) + ElementLine (40 0 100 0 10) + ElementLine (300 0 360 0 10) + ) + +Element(0x00000000 "R 0.25W" "R14" "100" 1105 1075 -265 60 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000001) + Pin(-400 0 60 30 90 28 "2" "2" 0x00000001) + ElementLine (-100 50 -300 50 10) + ElementLine (-300 50 -300 -50 10) + ElementLine (-300 -50 -100 -50 10) + ElementLine (-100 -50 -100 50 10) + ElementLine (-40 0 -100 0 10) + ElementLine (-300 0 -360 0 10) + ) + +Element(0x00000000 "R 0.5W" "R11" "" 2815 1700 60 -90 0 150 0x00000000) +( + Pin(0 0 85 30 115 48 "1" "1" 0x00000101) + Pin(0 -800 85 30 115 48 "2" "2" 0x00000001) + ElementLine (0 -60 0 -115 10) + ElementLine (-115 -115 115 -115 10) + ElementLine (115 -115 115 -685 10) + ElementLine (115 -685 -115 -685 10) + ElementLine (-115 -685 -115 -115 10) + ElementLine (0 -685 0 -750 10) + ) + +Element(0x00000000 "TK11950" "U3" "5.0V" 2235 1510 -139 -2 0 150 0x00000000) +( + Pad(-7 0 8 0 24 30 54 "NOISE BYPASS" "1" 0x00000100) + Pad(-7 37 8 37 24 30 54 "CONTROL" "2" 0x00000100) + Pad(-7 75 8 75 24 30 54 "RESET OUT" "3" 0x00000100) + Pad(119 75 134 75 24 30 54 "VO" "4" 0x00000100) + Pad(119 37 134 37 24 30 54 "GND" "5" 0x00000100) + Pad(119 0 134 0 24 30 54 "VIN" "6" 0x00000100) + ElementLine (0 -22 0 -34 10) + ElementLine (0 -34 132 -34 10) + ElementLine (132 -34 132 -22 10) + ElementLine (0 96 0 108 10) + ElementLine (0 108 132 108 10) + ElementLine (132 108 132 96 10) + ElementLine (13 -24 119 -24 10) + ) + +Element(0x00000000 "TK11950" "U4" "5.0V" 1180 1590 -254 -132 0 150 0x00000000) +( + Pad(7 0 -8 0 24 30 54 "NOISE BYPASS" "1" 0x00000100) + Pad(7 -37 -8 -37 24 30 54 "CONTROL" "2" 0x00000100) + Pad(7 -75 -8 -75 24 30 54 "RESET OUT" "3" 0x00000100) + Pad(-119 -75 -134 -75 24 30 54 "VO" "4" 0x00000100) + Pad(-119 -37 -134 -37 24 30 54 "GND" "5" 0x00000100) + Pad(-119 0 -134 0 24 30 54 "VIN" "6" 0x00000100) + ElementLine (0 22 0 34 10) + ElementLine (0 34 -132 34 10) + ElementLine (-132 34 -132 22 10) + ElementLine (0 -96 0 -108 10) + ElementLine (0 -108 -132 -108 10) + ElementLine (-132 -108 -132 -96 10) + ElementLine (-13 24 -119 24 10) + ) + +Element(0x00000000 "SMD 0805" "C5" "" 1495 1315 -225 -30 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(-90 0 -90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (-125 35 35 35 10) + ElementLine (-125 -35 -125 35 10) + ElementLine (35 -35 -125 -35 10) + ElementLine (35 35 35 -35 10) + ) + +Element(0x00000010 "SMD 0805" "C11" "" 2270 1420 -260 -30 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(-90 0 -90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (-125 35 35 35 10) + ElementLine (-125 -35 -125 35 10) + ElementLine (35 -35 -125 -35 10) + ElementLine (35 35 35 -35 10) + ) + +Element(0x00000000 "SMD Cap" "C9" "" 2030 1185 -145 -40 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x20200001) + Pin(200 0 80 30 110 35 "2" "2" 0x00000001) + ElementLine (0 45 0 50 10) + ElementLine (0 50 200 50 10) + ElementLine (200 50 200 45 10) + ElementLine (200 -45 200 -50 10) + ElementLine (200 -50 0 -50 10) + ElementLine (0 -50 0 -45 10) + ) + +Element(0x00000000 "R 0.25W" "R7" "100" 1655 2065 150 -30 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000001) + Pin(400 0 60 30 90 28 "2" "2" 0x00000001) + ElementLine (100 -50 300 -50 10) + ElementLine (300 -50 300 50 10) + ElementLine (300 50 100 50 10) + ElementLine (100 50 100 -50 10) + ElementLine (40 0 100 0 10) + ElementLine (300 0 360 0 10) + ) + +Element(0x00000000 "SMD Cap" "C8" "" 2030 1075 65 -124 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x20200001) + Pin(200 0 80 30 110 35 "2" "2" 0x00000001) + ElementLine (-50 -50 -50 50 10) + ElementLine (-50 50 250 50 10) + ElementLine (250 50 250 -50 10) + ElementLine (250 -50 -50 -50 10) + ) + +Element(0x00000000 "SMD Cap" "C7" "" 1530 1075 -370 -144 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x20200001) + Pin(-200 0 80 30 110 35 "2" "2" 0x10100001) + ElementLine (50 50 50 -50 10) + ElementLine (50 -50 -250 -50 10) + ElementLine (-250 -50 -250 50 10) + ElementLine (-250 50 50 50 10) + ) + +Element(0x00000000 "SMD Cap" "C2" "" 1945 1845 65 -19 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000101) + Pin(-200 0 80 30 110 35 "2" "2" 0x00000001) + ElementLine (50 50 50 -50 10) + ElementLine (50 -50 -250 -50 10) + ElementLine (-250 -50 -250 50 10) + ElementLine (-250 50 50 50 10) + ) + +Element(0x00000000 "SMD Cap" "C6" "" 1530 1185 -335 -30 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x20200001) + Pin(-200 0 80 30 110 35 "2" "2" 0x10100001) + ElementLine (0 -45 0 -50 10) + ElementLine (0 -50 -200 -50 10) + ElementLine (-200 -50 -200 -45 10) + ElementLine (-200 45 -200 50 10) + ElementLine (-200 50 0 50 10) + ElementLine (0 50 0 45 10) + ) + +Element(0x00000000 "SMD Cap" "C1" "" 1490 1950 -40 71 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000101) + Pin(0 -200 80 30 110 35 "2" "2" 0x00000001) + ElementLine (-50 50 50 50 10) + ElementLine (50 50 50 -250 10) + ElementLine (50 -250 -50 -250 10) + ElementLine (-50 -250 -50 50 10) + ) + +Element(0x00000000 "R 0.25W" "R6" "100" 2375 1680 65 115 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (50 100 50 300 10) + ElementLine (50 300 -50 300 10) + ElementLine (-50 300 -50 100 10) + ElementLine (-50 100 50 100 10) + ElementLine (0 40 0 100 10) + ElementLine (0 300 0 360 10) + ) + +Element(0x00000000 "R 0.25W" "R8" "100" 2270 1680 -30 245 1 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (50 100 50 300 10) + ElementLine (50 300 -50 300 10) + ElementLine (-50 300 -50 100 10) + ElementLine (-50 100 50 100 10) + ElementLine (0 40 0 100 10) + ElementLine (0 300 0 360 10) + ) + +Element(0x00000000 "R 0.25W" "R5" "100" 1375 1750 -170 175 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (50 100 50 300 10) + ElementLine (50 300 -50 300 10) + ElementLine (-50 300 -50 100 10) + ElementLine (-50 100 50 100 10) + ElementLine (0 40 0 100 10) + ElementLine (0 300 0 360 10) + ) + +Element(0x00000000 "R 0.25W" "R9" "100" 1655 2170 125 -25 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000001) + Pin(400 0 60 30 90 28 "2" "2" 0x00000001) + ElementLine (100 -50 300 -50 10) + ElementLine (300 -50 300 50 10) + ElementLine (300 50 100 50 10) + ElementLine (100 50 100 -50 10) + ElementLine (40 0 100 0 10) + ElementLine (300 0 360 0 10) + ) + +Element(0x00000000 "R 0.25W" "R10" "100" 2160 1675 -30 275 1 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (50 100 50 300 10) + ElementLine (50 300 -50 300 10) + ElementLine (-50 300 -50 100 10) + ElementLine (-50 100 50 100 10) + ElementLine (0 40 0 100 10) + ElementLine (0 300 0 360 10) + ) + +Element(0x00000000 "ADC12138CIMSA" "U2" "ADC12138" 1630 1690 105 -449 0 150 0x00000000) +( + Pad(0 30 0 -30 12 30 42 "CH0" "1" 0x00000100) + Pad(26 30 26 -30 12 30 42 "CH1" "2" 0x00000100) + Pad(51 30 51 -30 12 30 42 "CH2" "3" 0x00000100) + Pad(77 30 77 -30 12 30 42 "CH3" "4" 0x00000100) + Pad(102 30 102 -30 12 30 42 "CH4" "5" 0x00000100) + Pad(128 30 128 -30 12 30 42 "CH5" "6" 0x00000100) + Pad(154 30 154 -30 12 30 42 "CH6" "7" 0x00000100) + Pad(179 30 179 -30 12 30 42 "CH7" "8" 0x00000100) + Pad(205 30 205 -30 12 30 42 "COM" "9" 0x00000100) + Pad(230 30 230 -30 12 30 42 "MuOut1" "10" 0x00000100) + Pad(256 30 256 -30 12 30 42 "A/Din1" "11" 0x00000100) + Pad(281 30 281 -30 12 30 42 "MuxOut2" "12" 0x00000100) + Pad(307 30 307 -30 12 30 42 "A/Din2" "13" 0x00000100) + Pad(333 30 333 -30 12 30 42 "DGND" "14" 0x00000100) + Pad(333 -350 333 -290 12 30 42 "VA+" "15" 0x00000100) + Pad(307 -350 307 -290 12 30 42 "Vref-" "16" 0x00000100) + Pad(281 -350 281 -290 12 30 42 "Vref+" "17" 0x00000100) + Pad(256 -350 256 -290 12 30 42 "AGND" "18" 0x00000100) + Pad(230 -350 230 -290 12 30 42 "PD" "19" 0x00000100) + Pad(205 -350 205 -290 12 30 42 "EOC" "20" 0x00000100) + Pad(179 -350 179 -290 12 30 42 "~CONV" "21" 0x00000100) + Pad(154 -350 154 -290 12 30 42 "~CS" "22" 0x00000100) + Pad(128 -350 128 -290 12 30 42 "DO" "23" 0x00000100) + Pad(102 -350 102 -290 12 30 42 "DI" "24" 0x00000100) + Pad(77 -350 77 -290 12 30 42 "SCLK" "25" 0x00000100) + Pad(51 -350 51 -290 12 30 42 "CCLK" "26" 0x00000100) + Pad(26 -350 26 -290 12 30 42 "~DOR" "27" 0x00000100) + Pad(0 -350 0 -290 12 30 42 "VD+" "28" 0x00000100) + ElementLine (0 -70 0 -70 30) + ElementLine (-12 -54 -37 -54 10) + ElementLine (-37 -54 -37 -266 10) + ElementLine (-37 -266 -12 -266 10) + ElementLine (343 -54 370 -54 10) + ElementLine (370 -54 370 -266 10) + ElementLine (370 -266 343 -266 10) + ) + +Element(0x00000000 "R 0.25W" "R4" "100" 1615 1955 130 -35 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(400 0 60 30 90 28 "2" "2" 0x00000001) + ElementLine (100 -50 300 -50 10) + ElementLine (300 -50 300 50 10) + ElementLine (300 50 100 50 10) + ElementLine (100 50 100 -50 10) + ElementLine (40 0 100 0 10) + ElementLine (300 0 360 0 10) + ) + +Element(0x00000010 "SMD 0805" "C4" "" 2070 2390 -25 -180 0 115 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(0 -90 0 -90 60 30 90 "2" "2" 0x00000100) + ElementLine (-35 -125 -35 35 10) + ElementLine (35 -125 -35 -125 10) + ElementLine (35 35 35 -125 10) + ElementLine (-35 35 35 35 10) + ) + +Element(0x00000000 "R 0.25W" "R1" "100" 2180 2625 -35 -145 1 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 -400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (-50 -100 -50 -300 10) + ElementLine (-50 -300 50 -300 10) + ElementLine (50 -300 50 -100 10) + ElementLine (50 -100 -50 -100 10) + ElementLine (0 -40 0 -100 10) + ElementLine (0 -300 0 -360 10) + ) + +Element(0x00000000 "R 0.25W" "R2" "100" 2400 2625 60 -100 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 -400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (-50 -100 -50 -300 10) + ElementLine (-50 -300 50 -300 10) + ElementLine (50 -300 50 -100 10) + ElementLine (50 -100 -50 -100 10) + ElementLine (0 -40 0 -100 10) + ElementLine (0 -300 0 -360 10) + ) + +Element(0x00000000 "LM13700" "U1" "LM13700" 1955 2285 -475 -130 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "Iabc1" "1" 0x00000101) + Pin(-100 0 60 30 90 28 "Dbias1" "2" 0x00000001) + Pin(-200 0 60 30 90 28 "In+1" "3" 0x00000001) + Pin(-300 0 60 30 90 28 "In-1" "4" 0x00000001) + Pin(-400 0 60 30 90 28 "Out1" "5" 0x00000001) + Pin(-500 0 60 30 90 28 "V-" "6" 0x00000001) + Pin(-600 0 60 30 90 28 "BufIn1" "7" 0x00000001) + Pin(-700 0 60 30 90 28 "BufOut1" "8" 0x00000001) + Pin(-700 300 60 30 90 28 "BufOut2" "9" 0x00000001) + Pin(-600 300 60 30 90 28 "BufIn2" "10" 0x00000001) + Pin(-500 300 60 30 90 28 "V+" "11" 0x00000001) + Pin(-400 300 60 30 90 28 "Out2" "12" 0x00000001) + Pin(-300 300 60 30 90 28 "In-2" "13" 0x00000001) + Pin(-200 300 60 30 90 28 "In+2" "14" 0x00000001) + Pin(-100 300 60 30 90 28 "Dbias2" "15" 0x00000001) + Pin(0 300 60 30 90 28 "Iabc2" "16" 0x00000001) + ElementLine (50 -50 -750 -50 10) + ElementLine (-750 -50 -750 350 10) + ElementLine (-750 350 50 350 10) + ElementLine (50 -50 50 100 10) + ElementLine (50 200 50 350 10) + ElementArc (50 150 50 50 270 180 10) + ) + +Element(0x00000000 "R 0.25W" "R3" "100" 2290 2625 -30 -135 1 150 0x00000000) +( + Pin(0 0 60 30 90 28 "1" "1" 0x00000101) + Pin(0 -400 60 30 90 28 "2" "2" 0x00000001) + ElementLine (-50 -100 -50 -300 10) + ElementLine (-50 -300 50 -300 10) + ElementLine (50 -300 50 -100 10) + ElementLine (50 -100 -50 -100 10) + ElementLine (0 -40 0 -100 10) + ElementLine (0 -300 0 -360 10) + ) + +Element(0x00000000 "SMD 0805" "C3" "" 2075 2510 -40 140 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(0 90 0 90 60 30 90 "2" "2" 0x00000100) + ElementLine (35 125 35 -35 10) + ElementLine (-35 125 35 125 10) + ElementLine (-35 -35 -35 125 10) + ElementLine (35 -35 -35 -35 10) + ) + +Element(0x00000000 "3 TERM BLOCK" "J2" "DK ED1602-ND" 1695 2925 -590 76 0 150 0x00000000) +( + Pin(0 0 110 30 140 48 "1" "1" 0x00000001) + Pin(-194 0 110 30 140 48 "2" "2" 0x00000001) + Pin(-388 0 110 30 140 48 "3" "3" 0x00000001) + ElementLine (-388 160 -388 140 10) + ElementLine (-194 160 -194 140 10) + ElementLine (0 160 0 140 10) + ElementLine (81 -170 101 -170 10) + ElementLine (81 -190 81 -170 10) + ElementLine (101 -190 81 -190 10) + ElementLine (-509 -170 -489 -170 10) + ElementLine (-509 -190 -509 -170 10) + ElementLine (-489 -190 -509 -190 10) + ElementLine (101 -200 101 160 10) + ElementLine (-489 -200 101 -200 10) + ElementLine (-489 160 -489 -200 10) + ElementLine (101 160 -489 160 10) + ) + +Element(0x00000000 "SMD Cap" "C21" "" 2565 1070 -50 61 0 150 0x00000000) +( + Pin(0 0 80 30 110 35 "1" "1" 0x00000001) + Pin(-200 0 80 30 110 35 "2" "2" 0x00000001) + ElementLine (50 50 50 -50 10) + ElementLine (50 -50 -250 -50 10) + ElementLine (-250 -50 -250 50 10) + ElementLine (-250 50 50 50 10) + ) + +Element(0x00000000 "SMD 0805" "C20" "" 2665 2375 -115 55 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(-90 0 -90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (-125 35 35 35 10) + ElementLine (-125 -35 -125 35 10) + ElementLine (35 -35 -125 -35 10) + ElementLine (35 35 35 -35 10) + ) + +Element(0x00000000 "SMD 0805" "C19" "" 2785 2375 -20 55 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(90 0 90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (125 -35 -35 -35 10) + ElementLine (125 35 125 -35 10) + ElementLine (-35 35 125 35 10) + ElementLine (-35 -35 -35 35 10) + ) + +Element(0x00000000 "SMD 0805" "C18" "" 2665 1800 155 -20 0 150 0x00000000) +( + Pad(0 0 0 0 60 30 90 "1" "1" 0x00000100) + Pad(90 0 90 0 60 30 90 "2" "2" 0x00000100) + ElementLine (125 -35 -35 -35 10) + ElementLine (125 35 125 -35 10) + ElementLine (-35 35 125 35 10) + ElementLine (-35 -35 -35 35 10) + ) + +Element(0x00000000 "AMP 745781-4" "J3" "A2100-ND" 820 1610 -125 837 0 150 0x00000000) +( + Pin(0 432 80 30 110 42 "1" "1" 0x00000101) + Pin(0 324 80 30 110 42 "2" "2" 0x00000001) + Pin(0 216 80 30 110 42 "3" "3" 0x00000001) + Pin(0 108 80 30 110 42 "4" "4" 0x00000001) + Pin(0 0 80 30 110 42 "5" "5" 0x00000001) + Pin(-112 378 80 30 110 42 "6" "6" 0x00000001) + Pin(-112 270 80 30 110 42 "7" "7" 0x00000001) + Pin(-112 162 80 30 110 42 "8" "8" 0x00000001) + Pin(-112 54 80 30 110 42 "9" "9" 0x00000001) + Pin(-56 -276 120 30 150 120 "MOUNT HOLE" "10" 0x00000009) + Pin(-56 708 120 30 150 120 "MOUNT HOLE" "11" 0x00000009) + ElementLine (-317 -390 58 -390 10) + ElementLine (-317 -138 -317 -390 10) + ElementLine (-433 455 -434 -22 10) + ElementLine (-317 823 -317 571 10) + ElementLine (58 823 -317 823 10) + ElementLine (58 -390 58 823 10) + ElementArc (-375 -138 58 58 90 90 10) + ElementArc (-375 -22 58 58 270 90 10) + ElementArc (-375 455 58 58 0 90 10) + ElementArc (-375 571 58 58 180 90 10) + ) + +Element(0x00000000 "3 TERM BLOCK" "J1" "DK ED1602-ND" 2285 2925 140 51 0 150 0x00000000) +( + Pin(0 0 110 30 140 48 "1" "1" 0x00000001) + Pin(-194 0 110 30 140 48 "2" "2" 0x00000001) + Pin(-388 0 110 30 140 48 "3" "3" 0x00000001) + ElementLine (-388 160 -388 140 10) + ElementLine (-194 160 -194 140 10) + ElementLine (0 160 0 140 10) + ElementLine (81 -170 101 -170 10) + ElementLine (81 -190 81 -170 10) + ElementLine (101 -190 81 -190 10) + ElementLine (-509 -170 -489 -170 10) + ElementLine (-509 -190 -509 -170 10) + ElementLine (-489 -190 -509 -190 10) + ElementLine (101 -200 101 160 10) + ElementLine (-489 -200 101 -200 10) + ElementLine (-489 160 -489 -200 10) + ElementLine (101 160 -489 160 10) + ) + +Element(0x00000000 "OP-AMP" "U7" "LTC1152" 2575 1925 380 200 0 150 0x00000000) +( + Pin(0 0 60 30 90 28 "SHDN" "1" 0x00000101) + Pin(0 100 60 30 90 28 "-IN" "2" 0x00000001) + Pin(0 200 60 30 90 28 "+IN" "3" 0x00000001) + Pin(0 300 60 30 90 28 "V-" "4" 0x00000001) + Pin(300 300 60 30 90 28 "COMP" "5" 0x00000001) + Pin(300 200 60 30 90 28 "OUT" "6" 0x00000001) + Pin(300 100 60 30 90 28 "V+" "7" 0x00000001) + Pin(300 0 60 30 90 28 "CP" "8" 0x00000001) + ElementLine (-50 -50 -50 350 10) + ElementLine (-50 350 350 350 10) + ElementLine (350 350 350 -50 10) + ElementLine (-50 -50 100 -50 10) + ElementLine (200 -50 350 -50 10) + ElementArc (150 -50 50 50 0 180 10) + ) + +Element(0x00000000 "R 0.5W" "R12" "" 1035 1935 -205 700 0 150 0x00000000) +( + Pin(0 0 85 30 115 48 "1" "1" 0x00000101) + Pin(0 800 90 30 120 48 "2" "2" 0x00000001) + ElementLine (0 60 0 115 10) + ElementLine (115 115 -115 115 10) + ElementLine (-115 115 -115 685 10) + ElementLine (-115 685 115 685 10) + ElementLine (115 685 115 115 10) + ElementLine (0 685 0 750 10) + ) +Rat(2630 850 1 2155 815 1 0x00000010) +Rat(2330 550 1 2155 615 1 0x00000010) +Rat(2354 1547 0 2515 1415 0 0x00000010) +Rat(2230 1075 1 2365 1070 1 0x00000010) +Rat(2230 1185 1 2230 1075 1 0x00000010) +Rat(2185 1310 0 2230 1185 1 0x00000010) +Rat(1790 1570 1 1885 1460 0 0x00000010) +Rat(2055 2065 1 1835 1720 0 0x00000010) +Rat(2055 2065 1 2055 2170 1 0x00000010) +Rat(2160 2075 1 2055 2065 1 0x00000010) +Rat(2575 2225 0 2160 2075 1 0x00000010) +Rat(1595 860 0 2155 815 1 0x00000010) +Rat(1175 1780 0 820 2042 1 0x00000010) +Rat(1280 1585 1 1175 1780 0 0x00000010) +Rat(1330 1185 1 1405 1315 0 0x00000010) +Rat(1187 1553 0 1061 1553 0 0x00000010) +Rat(1355 2285 1 2815 1700 1 0x00000010) +Rat(1200 2355 0 1035 2735 1 0x00000010) +Rat(1455 2585 1 1285 2355 0 0x00000010) +Rat(2100 1250 0 2095 1310 0 0x00000010) +Rat(2015 1955 1 2375 2080 1 0x00000010) +Rat(1707 1720 0 1655 2065 1 0x00000010) +Rat(1945 1845 1 2015 1955 1 0x00000010) +Rat(1707 1720 0 1945 1845 1 0x00000010) +Rat(1615 1955 1 1555 2285 1 0x00000010) +Rat(1745 1845 1 1615 1955 1 0x00000010) +Rat(1681 1720 0 1745 1845 1 0x00000010) +Rat(1655 2170 1 2270 2080 1 0x00000010) +Rat(1490 1950 1 1655 2170 1 0x00000010) +Rat(1490 1950 1 1375 2150 1 0x00000010) +Rat(1656 1720 0 1490 1950 1 0x00000010) +Rat(1600 1750 0 1555 2585 1 0x00000010) +Rat(1655 2285 1 1307 2925 1 0x00000010) +Rat(1755 2285 1 1501 2925 1 0x00000010) +Rat(2360 1315 0 2815 900 1 0x00000010) +Rat(705 595 1 820 1934 1 0x00000010) +Rat(705 695 1 820 1826 1 0x00000010) +Rat(1595 560 1 2155 615 1 0x00000010) +Rat(1530 1075 1 1595 560 1 0x00000010) +Rat(1495 1315 0 1530 1185 1 0x00000010) +Rat(1495 1315 0 1530 1435 1 0x00000010) +Rat(1080 1355 0 1495 1315 0 0x00000010) +Rat(2075 1455 1 2180 1420 0 0x00000010) +Rat(2180 1420 0 2185 1310 0 0x00000010) +Rat(2228 1547 0 2354 1547 0 0x00000010) +Layer(1 "solder") +( + Line(1005 1235 1065 1175 15 30 0x00000000) + Line(1010 980 1105 1075 15 30 0x00000000) + Line(1345 955 1405 955 15 30 0x00000000) + Line(1065 1175 1125 1175 15 30 0x00000000) + Line(1190 665 1295 560 15 30 0x00000000) + Line(705 895 705 1075 15 30 0x00000000) + Line(705 795 890 980 15 30 0x00000000) + Line(1005 695 1140 560 15 30 0x00000000) + Line(1945 1015 1945 1260 15 30 0x00000000) + Line(1135 665 1190 665 15 30 0x00000000) + Line(1105 1075 970 1210 15 30 0x00000000) + Line(890 980 1010 980 15 30 0x00000000) + Line(2460 965 1995 965 15 30 0x00000000) + Line(1855 2285 1855 2585 15 30 0x00000000) + Line(970 1210 970 1568 15 30 0x00000000) + Line(1005 795 1135 665 15 30 0x00000000) + Line(1405 955 1485 875 15 30 0x00000000) + Line(1995 965 1945 1015 15 30 0x00000000) + Line(1005 1315 1005 1235 15 30 0x00000000) + Line(2565 1070 2460 965 15 30 0x00000000) + Line(1945 1260 1985 1300 15 30 0x00000000) + Line(1125 1175 1345 955 15 30 0x00000000) + Line(2400 2625 2290 2625 10 30 0x00000000) + Line(970 1568 820 1718 15 30 0x00000000) + Line(1140 560 1195 560 15 30 0x00000000) + Line(1125 1435 1005 1315 15 30 0x00000000) + Text(525 2805 0 120 "LED (BACK)" 0x00000080) +) +Layer(2 "GND-solder") +( +) +Layer(3 "Vcc-solder") +( +) +Layer(4 "component") +( + Line(1732 1750 1732 1720 10 30 0x00000000) + Line(1911 1720 1937 1720 10 30 0x00000000) + Line(1985 1300 1937 1300 10 30 0x00000000) + Line(2015 985 1909 985 10 30 0x00000000) + Line(1860 1720 1886 1720 10 30 0x00000000) + Line(2075 2615 1985 2615 15 30 0x00000000) + Line(1950 2285 2070 2285 15 30 0x00000000) + Line(1795 2225 1315 2225 15 30 0x00000000) + Line(2125 2585 2290 2420 10 30 0x00000000) + Line(2075 2515 2075 2415 30 30 0x00000000) + Line(2070 2285 2120 2285 15 30 0x00000000) + Line(1490 1750 1375 1750 15 30 0x00000000) + Line(1520 2415 1455 2285 30 30 0x00000000) + Line(1315 2225 1255 2285 15 30 0x00000000) + Line(2160 1750 1732 1750 10 30 0x00000000) + Line(2160 1675 2440 1955 15 30 0x00000000) + Line(2160 1680 2160 1750 10 30 0x00000000) + Line(2440 2110 2345 2205 15 30 0x00000000) + Line(1490 1750 1600 1750 10 30 0x00000000) + Line(1190 1595 1190 1675 15 30 0x00000000) + Line(1190 1510 1190 1435 15 30 0x00000000) + Line(1190 1435 1130 1435 15 30 0x00000000) + Line(1695 860 1695 1276 10 30 0x00000000) + Line(1795 860 1732 923 10 30 0x00000000) + Line(1797 1015 1797 1225 10 30 0x00000000) + Line(1995 860 1927 927 10 30 0x00000000) + Line(1495 560 1646 711 10 30 0x00000000) + Line(1657 973 1657 1279 10 30 0x00000000) + Line(1657 1279 1681 1303 10 30 0x00000000) + Line(1681 1303 1681 1340 10 30 0x00000000) + Line(1927 927 1885 927 10 30 0x00000000) + Line(1895 860 1758 997 10 30 0x00000000) + Line(1732 923 1732 1340 10 30 0x00000000) + Line(1893 959 1829 1024 10 30 0x00000000) + Line(1646 962 1657 973 10 30 0x00000000) + Line(1797 1225 1784 1239 10 30 0x00000000) + Line(1646 711 1646 962 10 30 0x00000000) + Line(1895 560 2055 720 10 30 0x00000000) + Line(1885 927 1797 1015 10 30 0x00000000) + Line(2090 910 2015 985 10 30 0x00000000) + Line(1985 2615 1955 2585 15 30 0x00000000) + Line(1758 997 1758 1340 10 30 0x00000000) + Line(1707 1288 1707 1340 10 30 0x00000000) + Line(2235 1475 2275 1435 15 30 0x00000000) + Line(1909 985 1860 1035 10 30 0x00000000) + Line(1005 1195 1005 895 35 30 0x00000000) + Line(1060 1255 1005 1195 35 30 0x00000000) + Line(585 2350 585 1787 35 30 0x00000000) + Line(1860 1035 1860 1261 10 30 0x00000000) + Line(2675 2125 2575 2025 15 30 0x00000000) + Line(2555 475 1480 475 15 30 0x00000000) + Line(2630 550 2555 475 15 30 0x00000000) + Line(1455 2285 1290 2450 35 30 0x00000000) + Line(2090 655 2090 910 10 30 0x00000000) + Line(2120 2285 2180 2225 15 30 0x00000000) + Line(1995 560 2090 655 10 30 0x00000000) + Line(705 1075 635 1145 15 30 0x00000000) + Line(2290 2420 2290 2225 10 30 0x00000000) + Line(1480 475 1395 560 15 30 0x00000000) + Line(635 1425 820 1610 15 30 0x00000000) + Line(1809 1263 1809 1340 10 30 0x00000000) + Line(2075 2615 2125 2615 10 30 0x00000000) + Line(1290 2450 685 2450 35 30 0x00000000) + Line(1600 1750 1630 1720 10 30 0x00000000) + Line(1897 2827 1897 2925 15 30 0x00000000) + Line(2055 720 2055 895 10 30 0x00000000) + Line(1835 1285 1835 1340 10 30 0x00000000) + Line(1755 2585 2091 2925 15 30 0x00000000) + Line(2235 1500 2235 1475 15 30 0x00000000) + Line(1655 2585 1897 2827 15 30 0x00000000) + Line(2875 1800 2755 1800 15 30 0x00000000) + Line(2075 2415 1520 2415 30 30 0x00000000) + Line(1855 2285 1795 2225 15 30 0x00000000) + Line(2055 895 1991 959 10 30 0x00000000) + Line(1829 1024 1829 1244 10 30 0x00000000) + Line(1991 959 1893 959 10 30 0x00000000) + Line(2125 2615 2125 2585 10 30 0x00000000) + Line(2495 2530 2400 2625 15 30 0x00000000) + Line(2440 1955 2440 2110 15 30 0x00000000) + Line(2345 2865 2285 2925 15 30 0x00000000) + Line(2345 2205 2345 2865 15 30 0x00000000) + Line(2785 2215 2785 2375 15 30 0x00000000) + Line(1860 1261 1835 1285 10 30 0x00000000) + Line(2875 2225 2875 2375 15 30 0x00000000) + Line(1784 1239 1784 1340 10 30 0x00000000) + Line(2575 2125 2495 2215 15 30 0x00000000) + Line(2665 2375 2785 2375 15 30 0x00000000) + Line(2575 2225 2575 2375 15 30 0x00000000) + Line(2495 2215 2495 2530 15 30 0x00000000) + Line(2875 1925 2875 1800 15 30 0x00000000) + Line(2875 2125 2785 2215 15 30 0x00000000) + Line(1937 1300 1937 1340 10 30 0x00000000) + Line(2875 2125 2675 2125 15 30 0x00000000) + Line(635 1145 635 1425 15 30 0x00000000) + Line(2180 2625 2290 2625 15 30 0x00000000) + Line(1695 1276 1707 1288 10 30 0x00000000) + Line(685 2450 585 2350 35 30 0x00000000) + Line(2975 1480 2565 1070 15 30 0x00000000) + Line(2975 2025 2975 1480 15 30 0x00000000) + Line(2875 2125 2975 2025 15 30 0x00000000) + Line(1829 1244 1809 1263 10 30 0x00000000) + Line(585 1787 708 1664 35 30 0x00000000) + Text(2515 2705 0 140 "LED rev 1" 0x00000000) +) +Layer(5 "GND-component") +( + Line(1505 950 1595 860 30 30 0x00000000) + Line(1440 950 1505 950 30 30 0x00000000) + Line(2220 1545 2155 1545 20 30 0x00000000) + Line(2515 1350 2515 1415 30 30 0x00000000) + Line(1200 1350 1230 1350 35 30 0x00000000) + Line(1860 1395 1860 1430 10 30 0x00000000) + Line(1965 1495 1965 1635 25 30 0x00000000) + Line(1855 1495 1965 1495 25 30 0x00000000) + Line(1835 1665 1835 1625 10 30 0x00000000) + Line(1885 1395 1885 1460 10 30 0x00000000) + Line(1965 1660 1965 1635 10 30 0x00000000) + Line(1810 1665 1810 1630 10 30 0x00000000) + Line(1785 1660 1785 1625 10 30 0x00000000) + Line(1760 1625 1760 1660 10 30 0x00000000) + Line(1280 1580 1280 1490 25 30 0x00000000) + Line(1195 1555 1280 1555 20 30 0x00000000) + Line(2545 1320 2515 1350 30 30 0x00000000) + Line(1005 595 1085 595 30 30 0x00000000) + Line(1085 595 1085 955 30 30 0x00000000) + Line(1085 955 1145 1015 30 30 0x00000000) + Line(1145 1015 1245 1015 30 30 0x00000000) + Arc(1445 995 45 45 30 30 270 90 0x00000000) + Polygon(0x00000010) + ( + (2250 1535) (2270 1535) (2270 1485) (2325 1485) (2325 1535) + (2345 1535) (2345 1560) (2325 1560) (2325 1630) (2160 1630) + (2160 1610) (2270 1610) (2270 1560) (2250 1560) + ) + Polygon(0x00000010) + ( + (1995 1470) (1880 1470) (1880 1450) (2015 1450) (2015 1365) + (2160 1365) (2160 1330) (2195 1330) (2195 1425) (2160 1460) + (2160 1630) (2070 1630) (2070 1720) (1995 1720) + ) + Polygon(0x00000010) + ( + (1370 1635) (1930 1635) (1930 1525) (1370 1525) + ) + Polygon(0x00000010) + ( + (1865 1510) (1225 1510) (1225 995) (1415 995) (1415 1255) + (1365 1255) (1365 1365) (1605 1365) (1605 1415) (1865 1415) + ) + Polygon(0x00000000) + ( + (1360 1295) (1390 1295) (1390 1335) (1360 1335) + ) + Polygon(0x00000010) + ( + (1070 1565) (1090 1565) (1090 1810) (1150 1810) (1150 1765) + (1125 1740) (1125 1640) (1145 1640) (1145 1565) (1165 1565) + (1165 1540) (1145 1540) (1145 1485) (1090 1485) (1090 1540) + (1070 1540) + ) +) +Layer(6 "Vcc-component") +( + Line(1045 1870 1045 1935 25 30 0x00000000) + Line(708 2155 708 1988 40 30 0x00000000) + Line(2575 1925 2490 2010 25 30 0x00000000) + Line(1630 1340 1630 1250 10 30 0x00000000) + Line(1910 1430 1965 1430 10 30 0x00000000) + Line(1910 1395 1910 1430 10 30 0x00000000) + Line(1200 2355 1000 2155 35 30 0x00000000) + Line(2575 1925 2485 1835 25 30 0x00000000) + Line(1070 1265 1070 1330 25 30 0x00000000) + Line(2360 1500 2360 1315 25 30 0x00000000) + Line(2445 1250 2445 1675 30 30 0x00000000) + Line(2100 1250 2445 1250 30 30 0x00000000) + Line(1910 1340 1910 1250 10 30 0x00000000) + Line(1965 1430 1965 1400 10 30 0x00000000) + Line(2375 1585 2440 1585 25 30 0x00000000) + Line(2665 1835 2575 1925 30 30 0x00000000) + Line(1120 1875 1190 1875 20 30 0x00000000) + Line(1045 1595 1045 1875 20 30 0x00000000) + Line(1045 1875 1120 1875 20 30 0x00000000) + Line(2875 2025 2675 2025 25 30 0x00000000) + Line(1285 2355 1200 2355 35 30 0x00000000) + Line(1355 2285 1285 2355 35 30 0x00000000) + Line(2675 2025 2575 1925 25 30 0x00000000) + Line(1000 2155 708 2155 40 30 0x00000000) + Line(1060 1510 1060 1375 25 30 0x00000000) + Line(1190 1875 1280 1785 20 30 0x00000000) + Line(2490 2010 2490 2135 25 30 0x00000000) + Line(2450 1510 2495 1510 35 30 0x00000000) + Line(2485 1835 2485 1680 25 30 0x00000000) + Line(2485 1680 2375 1680 25 30 0x00000000) + Line(2665 1800 2665 1835 30 30 0x00000000) + Line(2375 1680 2270 1680 30 30 0x00000000) + Line(2490 2135 2400 2225 25 30 0x00000000) + Polygon(0x00000000) + ( + (1500 1255) (1530 1255) (1530 1295) (1500 1295) + ) + Polygon(0x00000010) + ( + (1445 1255) (1635 1255) (1635 995) (1635 995) (1635 995) + (1635 995) (1635 995) (1445 995) + ) + Polygon(0x00000010) + ( + (1885 1260) (2120 1260) (2120 1005) (1921 1003) (1885 1039) + ) + Polygon(0x00000000) + ( + (2080 1250) (2110 1250) (2110 1295) (2080 1295) + ) +) +Layer(7 "unused") +( +) +Layer(8 "unused") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( + Text(2210 3120 0 115 "ANODE" 0x00000400) + Text(1855 3125 0 115 "-Y" 0x00000400) + Text(2045 3130 0 115 "+Y" 0x00000400) + Text(1255 3125 0 115 "-X" 0x00000400) + Text(1455 3125 0 115 "+X" 0x00000400) + Text(525 295 0 280 "FLARE GENESIS" 0x00000400) + Text(435 2815 0 165 "LED Interface" 0x00000400) + Text(1885 285 0 295 "harry eaton" 0x00000400) +) +NetList() +( + Net("AGND" "(unknown)") + ( + Connect("C8-2") + Connect("C9-2") + Connect("C10-2") + Connect("C11-2") + Connect("C12-2") + Connect("C13-2") + Connect("C20-2") + Connect("C21-2") + Connect("R7-2") + Connect("R9-2") + Connect("R10-2") + Connect("U2-6") + Connect("U2-7") + Connect("U2-8") + Connect("U2-9") + Connect("U2-18") + Connect("U3-2") + Connect("U3-5") + Connect("U7-4") + ) + Net("DGND" "(unknown)") + ( + Connect("C5-2") + Connect("C6-2") + Connect("C7-2") + Connect("C14-2") + Connect("C15-2") + Connect("C16-2") + Connect("C17-1") + Connect("J3-1") + Connect("U2-14") + Connect("U2-19") + Connect("U4-2") + Connect("U4-5") + Connect("U5-5") + Connect("U6-4") + Connect("X1-2") + ) + Net("Minus12V" "(unknown)") + ( + Connect("C3-1") + Connect("C4-1") + Connect("J3-9") + Connect("U1-6") + ) + Net("Plus12V" "(unknown)") + ( + Connect("J3-6") + Connect("R11-1") + Connect("R12-2") + Connect("U1-7") + Connect("U1-11") + ) + Net("S00001" "(unknown)") + ( + Connect("C8-1") + Connect("C9-1") + Connect("C10-1") + Connect("C13-1") + Connect("C18-1") + Connect("R2-2") + Connect("R6-1") + Connect("R8-1") + Connect("U2-15") + Connect("U2-17") + Connect("U3-4") + Connect("U7-1") + Connect("U7-7") + ) + Net("SIG10" "Skinny") + ( + Connect("U1-2") + Connect("U1-8") + Connect("U1-15") + ) + Net("SIG41" "Power") + ( + Connect("C3-2") + Connect("R3-2") + Connect("U1-16") + ) + Net("SIG43" "(unknown)") + ( + Connect("C4-2") + Connect("R1-2") + Connect("U1-1") + ) + Net("SIG49" "(unknown)") + ( + Connect("C2-1") + Connect("R4-2") + Connect("R6-2") + Connect("R7-1") + Connect("U2-4") + ) + Net("SIG50" "(unknown)") + ( + Connect("C2-2") + Connect("R4-1") + Connect("U1-5") + Connect("U2-3") + ) + Net("SIG51" "(unknown)") + ( + Connect("C1-1") + Connect("R5-2") + Connect("R8-2") + Connect("R9-1") + Connect("U2-2") + ) + Net("SIG52" "(unknown)") + ( + Connect("C1-2") + Connect("R5-1") + Connect("U1-12") + Connect("U2-1") + ) + Net("SIG87" "(unknown)") + ( + Connect("U2-10") + Connect("U2-11") + ) + Net("SIG88" "(unknown)") + ( + Connect("U2-12") + Connect("U2-13") + ) + Net("SIG91" "(unknown)") + ( + Connect("C19-1") + Connect("C20-1") + Connect("C21-1") + Connect("U2-16") + Connect("U7-2") + Connect("U7-6") + ) + Net("SIG100" "(unknown)") + ( + Connect("U2-21") + Connect("U5-11") + ) + Net("SIG101" "(unknown)") + ( + Connect("U2-20") + Connect("U5-10") + ) + Net("SIG124" "(unknown)") + ( + Connect("J2-3") + Connect("U1-4") + ) + Net("SIG125" "(unknown)") + ( + Connect("J2-2") + Connect("U1-3") + ) + Net("SIG127" "(unknown)") + ( + Connect("J1-2") + Connect("U1-14") + ) + Net("SIG139" "(unknown)") + ( + Connect("C11-1") + Connect("U3-1") + ) + Net("SIG146" "(unknown)") + ( + Connect("C12-1") + Connect("R11-2") + Connect("U3-6") + ) + Net("SIG150" "(unknown)") + ( + Connect("C15-1") + Connect("R12-1") + Connect("U4-6") + ) + Net("SIG155" "(unknown)") + ( + Connect("C14-1") + Connect("U4-1") + ) + Net("SIG191" "(unknown)") + ( + Connect("U5-16") + Connect("X1-3") + ) + Net("SIG241" "(unknown)") + ( + Connect("U2-26") + Connect("U5-15") + ) + Net("SIG252" "(unknown)") + ( + Connect("R13-1") + Connect("U4-3") + Connect("U5-4") + ) + Net("SIG258" "(unknown)") + ( + Connect("U5-18") + Connect("U6-3") + ) + Net("SIG259" "(unknown)") + ( + Connect("U5-17") + Connect("U6-2") + ) + Net("SIG285" "(unknown)") + ( + Connect("J3-4") + Connect("R14-1") + Connect("U6-7") + ) + Net("SIG286" "(unknown)") + ( + Connect("J3-5") + Connect("R14-2") + Connect("U6-8") + ) + Net("SIG291" "(unknown)") + ( + Connect("U2-22") + Connect("U5-9") + ) + Net("SIG292" "(unknown)") + ( + Connect("U2-23") + Connect("U5-8") + ) + Net("SIG293" "(unknown)") + ( + Connect("U2-24") + Connect("U5-7") + ) + Net("SIG294" "(unknown)") + ( + Connect("U2-25") + Connect("U5-6") + ) + Net("SIG296" "(unknown)") + ( + Connect("J3-2") + Connect("U6-5") + ) + Net("SIG297" "(unknown)") + ( + Connect("J3-3") + Connect("U6-6") + ) + Net("SIG310" "(unknown)") + ( + Connect("J1-1") + Connect("R10-1") + Connect("U2-5") + ) + Net("SIG311" "(unknown)") + ( + Connect("J1-3") + Connect("U1-13") + ) + Net("SIG321" "(unknown)") + ( + Connect("C5-1") + Connect("C6-1") + Connect("C7-1") + Connect("C16-1") + Connect("C17-2") + Connect("R13-2") + Connect("U2-28") + Connect("U4-4") + Connect("U5-14") + Connect("U6-1") + Connect("X1-4") + ) + Net("SIG338" "(unknown)") + ( + Connect("R1-1") + Connect("R2-1") + Connect("R3-1") + Connect("U7-3") + ) + Net("SIG341" "(unknown)") + ( + Connect("C18-2") + Connect("U7-8") + ) + Net("SIG343" "(unknown)") + ( + Connect("C19-2") + Connect("U7-5") + ) +) Index: tags/1.2.7/font/HersheySans1.pcb_font =================================================================== --- tags/1.2.7/font/HersheySans1.pcb_font (nonexistent) +++ tags/1.2.7/font/HersheySans1.pcb_font (revision 13657) @@ -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/1.2.7/font/default_arc.lht =================================================================== --- tags/1.2.7/font/default_arc.lht (nonexistent) +++ tags/1.2.7/font/default_arc.lht (revision 13657) @@ -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/1.2.7/font/osifontASCII.lht =================================================================== --- tags/1.2.7/font/osifontASCII.lht (nonexistent) +++ tags/1.2.7/font/osifontASCII.lht (revision 13657) @@ -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/1.2.7/pcblib/Makefile =================================================================== --- tags/1.2.7/pcblib/Makefile (nonexistent) +++ tags/1.2.7/pcblib/Makefile (revision 13657) @@ -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/1.2.7/pcblib/README =================================================================== --- tags/1.2.7/pcblib/README (nonexistent) +++ tags/1.2.7/pcblib/README (revision 13657) @@ -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/1.2.7/pcblib/connector/BNC_LAY.fp =================================================================== --- tags/1.2.7/pcblib/connector/BNC_LAY.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/BNC_LAY.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB15F.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB15F.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB15F.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB15M.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB15M.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB15M.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB25F.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB25F.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB25F.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB25M.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB25M.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB25M.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB37F.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB37F.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB37F.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB37M.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB37M.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB37M.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB9F.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB9F.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB9F.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/DB9M.fp =================================================================== --- tags/1.2.7/pcblib/connector/DB9M.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/DB9M.fp (revision 13657) @@ -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/1.2.7/pcblib/connector/pwrjack.fp =================================================================== --- tags/1.2.7/pcblib/connector/pwrjack.fp (nonexistent) +++ tags/1.2.7/pcblib/connector/pwrjack.fp (revision 13657) @@ -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/1.2.7/pcblib/parametric/acy =================================================================== --- tags/1.2.7/pcblib/parametric/acy (nonexistent) +++ tags/1.2.7/pcblib/parametric/acy (revision 13657) @@ -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/1.2.7/pcblib/parametric/acy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/acy.awk =================================================================== --- tags/1.2.7/pcblib/parametric/acy.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/acy.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/alf =================================================================== --- tags/1.2.7/pcblib/parametric/alf (nonexistent) +++ tags/1.2.7/pcblib/parametric/alf (revision 13657) @@ -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/1.2.7/pcblib/parametric/alf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/alf.awk =================================================================== --- tags/1.2.7/pcblib/parametric/alf.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/alf.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/bga =================================================================== --- tags/1.2.7/pcblib/parametric/bga (nonexistent) +++ tags/1.2.7/pcblib/parametric/bga (revision 13657) @@ -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/1.2.7/pcblib/parametric/bga ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/bga.awk =================================================================== --- tags/1.2.7/pcblib/parametric/bga.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/bga.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/common.awk =================================================================== --- tags/1.2.7/pcblib/parametric/common.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/common.awk (revision 13657) @@ -0,0 +1,599 @@ +#@@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"]) { + if (value ~ "mm") + value = mm(value) + else + value = mil(value) + } + 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 + } + } +} + +# Assume h is a dimension; if it has an "mm" suffix, convert it from mm, +# else convert it from mil. +function parse_dim(h) +{ + 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 + } + return mil(h) +} + +# 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, WANT,tmp) +{ + 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 ~ "^#@@") + print line + } + close(fn) + for(tmp in WANT) + help_extract(SEEN, tmp, dirn) +} + +function help_print( SEEN, dirn) +{ + print "#@@info-generator pcblib common.awk" + dirn = genfull + sub("/[^/]*$", "", dirn) + help_extract(SEEN, genfull, dirn) +} + +function help_auto() +{ + if ((args ~ "^--help") || (args ~ ",[ \t]*--help")) { + help_print() + exit(0) + } +} Index: tags/1.2.7/pcblib/parametric/connector =================================================================== --- tags/1.2.7/pcblib/parametric/connector (nonexistent) +++ tags/1.2.7/pcblib/parametric/connector (revision 13657) @@ -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/1.2.7/pcblib/parametric/connector ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/connector.awk =================================================================== --- tags/1.2.7/pcblib/parametric/connector.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/connector.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/dip =================================================================== --- tags/1.2.7/pcblib/parametric/dip (nonexistent) +++ tags/1.2.7/pcblib/parametric/dip (revision 13657) @@ -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/1.2.7/pcblib/parametric/dip ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/dip.awk =================================================================== --- tags/1.2.7/pcblib/parametric/dip.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/dip.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/msop =================================================================== --- tags/1.2.7/pcblib/parametric/msop (nonexistent) +++ tags/1.2.7/pcblib/parametric/msop (revision 13657) @@ -0,0 +1,28 @@ +#!/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 + + +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/1.2.7/pcblib/parametric/msop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/plcc =================================================================== --- tags/1.2.7/pcblib/parametric/plcc (nonexistent) +++ tags/1.2.7/pcblib/parametric/plcc (revision 13657) @@ -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/1.2.7/pcblib/parametric/plcc ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/plcc.awk =================================================================== --- tags/1.2.7/pcblib/parametric/plcc.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/plcc.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/qf =================================================================== --- tags/1.2.7/pcblib/parametric/qf (nonexistent) +++ tags/1.2.7/pcblib/parametric/qf (revision 13657) @@ -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/1.2.7/pcblib/parametric/qf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/qf.awk =================================================================== --- tags/1.2.7/pcblib/parametric/qf.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/qf.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/qfn =================================================================== --- tags/1.2.7/pcblib/parametric/qfn (nonexistent) +++ tags/1.2.7/pcblib/parametric/qfn (revision 13657) @@ -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/1.2.7/pcblib/parametric/qfn ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/qfn.awk =================================================================== --- tags/1.2.7/pcblib/parametric/qfn.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/qfn.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/qfp =================================================================== --- tags/1.2.7/pcblib/parametric/qfp (nonexistent) +++ tags/1.2.7/pcblib/parametric/qfp (revision 13657) @@ -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/1.2.7/pcblib/parametric/qfp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/qfp.awk =================================================================== --- tags/1.2.7/pcblib/parametric/qfp.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/qfp.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/qsop =================================================================== --- tags/1.2.7/pcblib/parametric/qsop (nonexistent) +++ tags/1.2.7/pcblib/parametric/qsop (revision 13657) @@ -0,0 +1,27 @@ +#!/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 + +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/1.2.7/pcblib/parametric/qsop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/rcy =================================================================== --- tags/1.2.7/pcblib/parametric/rcy (nonexistent) +++ tags/1.2.7/pcblib/parametric/rcy (revision 13657) @@ -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/1.2.7/pcblib/parametric/rcy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/rcy.awk =================================================================== --- tags/1.2.7/pcblib/parametric/rcy.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/rcy.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/screw =================================================================== --- tags/1.2.7/pcblib/parametric/screw (nonexistent) +++ tags/1.2.7/pcblib/parametric/screw (revision 13657) @@ -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/1.2.7/pcblib/parametric/screw ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/screw.awk =================================================================== --- tags/1.2.7/pcblib/parametric/screw.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/screw.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/silkmark.help =================================================================== --- tags/1.2.7/pcblib/parametric/silkmark.help (nonexistent) +++ tags/1.2.7/pcblib/parametric/silkmark.help (revision 13657) @@ -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/1.2.7/pcblib/parametric/so =================================================================== --- tags/1.2.7/pcblib/parametric/so (nonexistent) +++ tags/1.2.7/pcblib/parametric/so (revision 13657) @@ -0,0 +1,38 @@ +#!/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 250 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 + +awk -f `dirname $0`/common.awk -f `dirname $0`/so.awk -v "args=$*" -v gen=`basename $0` -v "genfull=$0" + Property changes on: tags/1.2.7/pcblib/parametric/so ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/so.awk =================================================================== --- tags/1.2.7/pcblib/parametric/so.awk (nonexistent) +++ tags/1.2.7/pcblib/parametric/so.awk (revision 13657) @@ -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/1.2.7/pcblib/parametric/ssop =================================================================== --- tags/1.2.7/pcblib/parametric/ssop (nonexistent) +++ tags/1.2.7/pcblib/parametric/ssop (revision 13657) @@ -0,0 +1,27 @@ +#!/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 + +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/1.2.7/pcblib/parametric/ssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/parametric/tssop =================================================================== --- tags/1.2.7/pcblib/parametric/tssop (nonexistent) +++ tags/1.2.7/pcblib/parametric/tssop (revision 13657) @@ -0,0 +1,28 @@ +#!/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 + + +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/1.2.7/pcblib/parametric/tssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/pcblib/smd/01005.fp =================================================================== --- tags/1.2.7/pcblib/smd/01005.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/01005.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/0201.fp =================================================================== --- tags/1.2.7/pcblib/smd/0201.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/0201.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/0402.fp =================================================================== --- tags/1.2.7/pcblib/smd/0402.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/0402.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/0603.fp =================================================================== --- tags/1.2.7/pcblib/smd/0603.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/0603.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/0805.fp =================================================================== --- tags/1.2.7/pcblib/smd/0805.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/0805.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/1008.fp =================================================================== --- tags/1.2.7/pcblib/smd/1008.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/1008.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/1206.fp =================================================================== --- tags/1.2.7/pcblib/smd/1206.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/1206.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/1206.scad =================================================================== --- tags/1.2.7/pcblib/smd/1206.scad (nonexistent) +++ tags/1.2.7/pcblib/smd/1206.scad (revision 13657) @@ -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/1.2.7/pcblib/smd/1210.fp =================================================================== --- tags/1.2.7/pcblib/smd/1210.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/1210.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/1806.fp =================================================================== --- tags/1.2.7/pcblib/smd/1806.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/1806.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/1825.fp =================================================================== --- tags/1.2.7/pcblib/smd/1825.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/1825.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/2706.fp =================================================================== --- tags/1.2.7/pcblib/smd/2706.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/2706.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/DO214.fp =================================================================== --- tags/1.2.7/pcblib/smd/DO214.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/DO214.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/DO214AB.fp =================================================================== --- tags/1.2.7/pcblib/smd/DO214AB.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/DO214AB.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/MPAK.fp =================================================================== --- tags/1.2.7/pcblib/smd/MPAK.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/MPAK.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SC70_3.fp =================================================================== --- tags/1.2.7/pcblib/smd/SC70_3.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SC70_3.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SC70_4.fp =================================================================== --- tags/1.2.7/pcblib/smd/SC70_4.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SC70_4.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SC90.fp =================================================================== --- tags/1.2.7/pcblib/smd/SC90.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SC90.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD106A.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD106A.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD106A.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD110.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD110.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD110.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD123.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD123.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD123.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD323.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD323.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD323.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD80.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD80.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD80.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOD87.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOD87.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOD87.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT143.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT143.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT143.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT223.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT223.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT223.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT23.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT23.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT23.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT23D.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT23D.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT23D.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT25.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT25.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT25.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT26.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT26.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT26.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT323.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT323.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT323.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT323D.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT323D.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT323D.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT325.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT325.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT325.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT326.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT326.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT326.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/SOT89.fp =================================================================== --- tags/1.2.7/pcblib/smd/SOT89.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/SOT89.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/TANT_A.fp =================================================================== --- tags/1.2.7/pcblib/smd/TANT_A.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/TANT_A.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/TANT_B.fp =================================================================== --- tags/1.2.7/pcblib/smd/TANT_B.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/TANT_B.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/TANT_C.fp =================================================================== --- tags/1.2.7/pcblib/smd/TANT_C.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/TANT_C.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/TANT_D.fp =================================================================== --- tags/1.2.7/pcblib/smd/TANT_D.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/TANT_D.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/minimelf.fp =================================================================== --- tags/1.2.7/pcblib/smd/minimelf.fp (nonexistent) +++ tags/1.2.7/pcblib/smd/minimelf.fp (revision 13657) @@ -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/1.2.7/pcblib/smd/sot23.scad =================================================================== --- tags/1.2.7/pcblib/smd/sot23.scad (nonexistent) +++ tags/1.2.7/pcblib/smd/sot23.scad (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC49.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC49.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC49.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC49U.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC49U.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC49U.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC49UH.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC49UH.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC49UH.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC49U_3.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC49U_3.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC49U_3.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC49U_3H.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC49U_3H.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC49U_3H.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC51U.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC51U.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC51U.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HC51UH.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HC51UH.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HC51UH.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/HEPTAWATT.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/HEPTAWATT.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/HEPTAWATT.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/LED3.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/LED3.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/LED3.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/LED5.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/LED5.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/LED5.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/MULTIWATT11.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/MULTIWATT11.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/MULTIWATT11.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/MULTIWATT15.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/MULTIWATT15.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/MULTIWATT15.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/MULTIWATT8.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/MULTIWATT8.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/MULTIWATT8.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/OSC14.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/OSC14.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/OSC14.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/PENTAWATT.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/PENTAWATT.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/PENTAWATT.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TACT_6x6_4p =================================================================== --- tags/1.2.7/pcblib/tru-hole/TACT_6x6_4p (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TACT_6x6_4p (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO126.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO126.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO126.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO126S.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO126S.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO126S.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO126SW.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO126SW.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO126SW.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO126W.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO126W.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO126W.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO18.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO18.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO18.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO218.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO218.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO218.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO220.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO220.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO220.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO220ACSTAND.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO220ACSTAND.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO220ACSTAND.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO220S.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO220S.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO220S.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO220SW.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO220SW.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO220SW.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO220W.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO220W.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO220W.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO247.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO247.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO247.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO247_2.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO247_2.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO247_2.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO251.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO251.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO251.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO264.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO264.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO264.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO39.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO39.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO39.fp (revision 13657) @@ -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/1.2.7/pcblib/tru-hole/TO92.fp =================================================================== --- tags/1.2.7/pcblib/tru-hole/TO92.fp (nonexistent) +++ tags/1.2.7/pcblib/tru-hole/TO92.fp (revision 13657) @@ -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/1.2.7/scconfig/Makefile =================================================================== --- tags/1.2.7/scconfig/Makefile (nonexistent) +++ tags/1.2.7/scconfig/Makefile (revision 13657) @@ -0,0 +1,105 @@ +# --- 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: 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 ../src_3rd/puplug/Makefile ../src_3rd/puplug/config.h + -$(MAKE) clean Index: tags/1.2.7/scconfig/README =================================================================== --- tags/1.2.7/scconfig/README (nonexistent) +++ tags/1.2.7/scconfig/README (revision 13657) @@ -0,0 +1,3 @@ +The configuration system that runs ./configure. + +The engine is scconfig. Index: tags/1.2.7/scconfig/Rev.h =================================================================== --- tags/1.2.7/scconfig/Rev.h (nonexistent) +++ tags/1.2.7/scconfig/Rev.h (revision 13657) @@ -0,0 +1 @@ +static const int myrev = 13584; Index: tags/1.2.7/scconfig/Rev.tab =================================================================== --- tags/1.2.7/scconfig/Rev.tab (nonexistent) +++ tags/1.2.7/scconfig/Rev.tab (revision 13657) @@ -0,0 +1,122 @@ +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/1.2.7/scconfig/cquote.c =================================================================== --- tags/1.2.7/scconfig/cquote.c (nonexistent) +++ tags/1.2.7/scconfig/cquote.c (revision 13657) @@ -0,0 +1,130 @@ +/* + pcb-rnd - quote file and pack it in a C string (ANSI C code) + Copyright (C) 2016 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 St, Fifth Floor, Boston, MA 02110-1301 USA + + Project page: http://repo.hu/projects/scconfig + Contact via email: scconfig [at] igor2.repo.hu +*/ + +#include + +void copy_strlit(const char *inds, const char *varname) +{ + int c, nl = 0, qt = 1, ind = 1; + + printf("#define NL \"\\n\"\n"); + printf("const char *%s = \\\n", varname); + + while((c = getc(stdin)) != EOF) { + if (ind) { + printf("%s", inds); + if (!nl) + printf(" "); + ind = 0; + } + if (nl) { + printf("NL "); + nl = 0; + } + if (qt) { + printf("\""); + qt = 0; + } + switch(c) { + case '\t': printf(" "); break; + case '\n': printf("\"\n"); nl = qt = ind = 1; break; + case '\r': break; + case '\\': printf("\\\\"); break; + case '"': printf("\\\""); break; + default: + if ((c < 32) || (c>126)) + printf("\\%3o", c); + else + putc(c, stdout); + } + } + if (!qt) + printf("\""); + if (nl) { + if (ind) + printf("%s", inds); + printf("NL"); + } + printf(";\n"); +} + +void copy_chrarr(const char *inds, const char *varname) +{ + int c, col = 16000; + + printf("/* (Using character array instead of string literal for long strings) */\n"); + printf("const char %s_arr[] = {", varname); + + while((c = getc(stdin)) != EOF) { + if (col > 60) { + printf("\n%s", inds); + col = 0; + } + switch(c) { + case '\t': col+=printf("'\\t',"); break; + case '\r': break; + case '\\': col+=printf("'\\\\',"); break; + case '\'': col+=printf("'\\\'',"); break; + case '\n': + col+=printf("'\\n',"); + col = 16000; + break; + default: + if ((c < 32) || (c>126)) + col+=printf("%d,", c); + else + col+=printf("'%c',", c); break; + } + } + printf("\n%s0};\n", inds); + printf("const char *%s = %s_arr;\n", varname, varname); + +} + + + +int main(int argc, char *argv[]) +{ + char *varname = "quoted_file"; + char *inds = "\t"; + char *banner = "/* Autogenerated by cquote.c - DO NOT EDIT */\n"; + char *cmd, *arg; + int n, lit = 0; + + for(n = 1; n < argc; n++) { + cmd = argv[n]; + arg = argv[n+1]; + while(*cmd == '-') cmd++; + switch(*cmd) { + case 'n': varname = arg; n++; break; + case 'i': inds = arg; n++; break; + case 'l': lit = 1; break; + } + } + + printf("%s", banner); + if (lit) + copy_strlit(inds, varname); + else + copy_chrarr(inds, varname); + return 0; +} Index: tags/1.2.7/scconfig/gen_conf.sh =================================================================== --- tags/1.2.7/scconfig/gen_conf.sh (nonexistent) +++ tags/1.2.7/scconfig/gen_conf.sh (revision 13657) @@ -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/1.2.7/scconfig/gen_conf.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/scconfig/gen_core_lists.sh =================================================================== --- tags/1.2.7/scconfig/gen_core_lists.sh (nonexistent) +++ tags/1.2.7/scconfig/gen_core_lists.sh (revision 13657) @@ -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/1.2.7/scconfig/gen_core_lists.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.7/scconfig/hooks.c =================================================================== --- tags/1.2.7/scconfig/hooks.c (nonexistent) +++ tags/1.2.7/scconfig/hooks.c (revision 13657) @@ -0,0 +1,902 @@ +#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 "1.2.7" + +#include "plugin_3state.h" + +#include "../src_3rd/puplug/scconfig_hooks.h" + +int want_intl = 0, want_coord_bits; + +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) +#include "plugins.h" + + {NULL, NULL, NULL, NULL} +}; + +static void help1(void) +{ + 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 to path\n"); + printf(" --debug build full debug version (-g -O0, extra asserts)\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(" --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"); +} + +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, "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); + 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)) { + want_intl = 1; + return 1; + } + else if (strcmp(key, "help") == 0) { + help1(); + arg_auto_print_options(stdout, " ", " ", disable_libs); + help2(); + exit(0); + } + + return arg_auto_set(key, value, disable_libs); +} + +/* 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 +*/ +void plugin_dep1(int require, const char *plugin, const char *deps_on) +{ + char buff[1024]; + const char *st_plugin, *st_deps_on; + + 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); + } + } + 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); + } + } + } + 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); + } + } +} + +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) +#include "plugins.h" +} + +void plugin_deps(int require) +{ +#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) plugin_dep1(require, plg, on); +#include "plugins.h" +} + + +/* 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(); + + /* DEFAULTS */ + put("/local/prefix", "/usr/local"); + +#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) +#include "plugins.h" + + put("/local/pcb/want_bison", sfalse); + put("/local/pcb/debug", 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) +#include "plugins.h" + return tainted; +} + + +/* Runs after all arguments are read and parsed */ +int hook_postarg() +{ + plugin_deps(0); + return 0; +} + + + +/* Runs when things should be detected for the host system */ +int hook_detect_host() +{ + pup_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); + require("fstools/mkdir", 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); +} + +/* 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; + const char *host_ansi, *host_ped, *target_ansi, *target_ped; + + want_gl = plug_is_enabled("hid_gtk2_gl"); + 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_nelma") || plug_is_enabled("export_gcode"); + want_stroke = plug_is_enabled("stroke"); + want_cairo = plug_is_enabled("export_bboard") | want_gtk3; + want_xml2 = plug_is_enabled("io_eagle"); + + 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"); + + { /* 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); + printf("DEBUG='%s'\n", get("/target/cc/cflags")); + } + } + + pup_hook_detect_target(); + + require("signal/names/*", 0, 0); + require("libs/env/setenv/*", 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/math/rint/*", 0, 0); + require("libs/math/round/*", 0, 0); + require("libs/userpass/getpwuid/*", 0, 0); + + if (require("libs/time/usleep/*", 0, 0) && require("libs/time/Sleep/*", 0, 0)) { + report_repeat("\nERROR: can not find usleep() or Sleep() - no idea how to sleep ms.\n\n"); + return 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_intl) { + require("libs/sul/gettext/presents", 0, 0); + if (!istrue(get("libs/sul/gettext/presents"))) { + report_repeat("\nERROR: intl support explicitly requested but gettext is not found on your system.\n\n"); + return 1; + } + put("/local/pcb/want_nls", strue); + } + else + put("/local/pcb/want_nls", sfalse); + + 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_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); + want_gl = 0; + } + 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_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"); + hook_custom_arg("Disable-hid_gtk2_gl", NULL); + } + else + put("/local/pcb/has_glu", strue); + } + + 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); + } + } + + /* 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_config", 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"); + 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("export_dsn")) + 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-gtk", NULL); + } + if (plug_is_enabled("puller")) { + report_repeat("WARNING: Since GLIB is not found, disabling the puller...\n"); + hook_custom_arg("Disable-puller", NULL); + } + if (plug_is_enabled("export_dsn")) { + report_repeat("WARNING: Since GLIB is not found, disabling the dsn pcb_exporter...\n"); + hook_custom_arg("Disable-export_dsn", 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", ""); + } + + 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, nelma, 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_nelma", 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); + 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_nelma, 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); + } + + /* 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); + + if (plug_is_enabled("gpmi")) { + require("libs/script/gpmi/presents", 0, 0); + if (!istrue(get("libs/script/gpmi/presents"))) { + report_repeat("WARNING: disabling the gpmi scripting because libgpmi is not found or not configured...\n"); + hook_custom_arg("Disable-gpmi", NULL); + } + } + + /* 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, *abs_name, *postfix; + char tmp[64]; + int need_stdint = 0; + + if (want_coord_bits == int_bits) { postfix="U"; chosen = "int"; abs_name="abs"; } + else if (want_coord_bits == long_bits) { postfix="UL"; chosen = "long int"; abs_name="labs"; } + else if (want_coord_bits == int64_bits) { postfix="ULL"; chosen = "int64_t"; abs_name="llabs"; need_stdint = 1; } + else if (want_coord_bits == long_long_bits) { postfix="ULL"; chosen = "long long int"; abs_name="llabs"; } + 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); + put("/local/pcb/coord_abs", abs_name); + + 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("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 int gpmi_config(void) +{ + char *tmp; + const char *gcfg = get("libs/script/gpmi/gpmi-config"); + int generr = 0; + + printf("Generating pcb-gpmi/Makefile.conf (%d)\n", generr |= tmpasm("../src_plugins/gpmi/pcb-gpmi", "Makefile.config.in", "Makefile.config")); + + + printf("Configuring gpmi packages...\n"); + tmp = str_concat("", "cd ../src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg && ", gcfg, " --pkggrp && ./configure", NULL); + generr |= system(tmp); + free(tmp); + + printf("Configuring gpmi plugin \"app\"\n"); + tmp = str_concat("", "cd ../src_plugins/gpmi//pcb-gpmi/gpmi_plugin && ", gcfg, " --app", NULL); + generr |= system(tmp); + free(tmp); + + printf("Finished configuring gpmi packages\n"); + + return generr; +} +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 *rev = "non-svn", *tmp; + int generr = 0; + int res = 0; + + tmp = svn_info(0, "../src", "Revision:"); + if (tmp != NULL) { + rev = str_concat("", "svn r", tmp, NULL); + free(tmp); + } + logprintf(0, "scconfig generate version info: version='%s' rev='%s'\n", version, rev); + put("/local/revision", rev); + put("/local/version", version); + put("/local/pup/sccbox", "../../scconfig/sccbox"); + + 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/hid_gtk2_gl", "opengl.h.in", "opengl.h")); + if (plug_is_enabled("gpmi")) + gpmi_config(); + + generr |= pup_hook_generate("../src_3rd/puplug"); + + + 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/want_nls", "Internationalization with gettext"); + 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) +#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/1.2.7/scconfig/menucfg.c =================================================================== --- tags/1.2.7/scconfig/menucfg.c (nonexistent) +++ tags/1.2.7/scconfig/menucfg.c (revision 13657) @@ -0,0 +1,71 @@ +#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_gpmi[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, "scripting", "gpmi settings -->", NULL, me_gpmi, 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/1.2.7/scconfig/plugin_3state.h =================================================================== --- tags/1.2.7/scconfig/plugin_3state.h (nonexistent) +++ tags/1.2.7/scconfig/plugin_3state.h (revision 13657) @@ -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/1.2.7/scconfig/plugins.h =================================================================== --- tags/1.2.7/scconfig/plugins.h (nonexistent) +++ tags/1.2.7/scconfig/plugins.h (revision 13657) @@ -0,0 +1,149 @@ +/****************************************************************************** + 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", sdisable, 0) +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_config", "hid_gtk preferences dialog", 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_legacy_func", "legacy functions", sbuildin, 1) +plugin_def("lib_netmap", "map nets and objects", sdisable, 0) +plugin_def("lib_padstack_hash","abstract and hash 'padstacks'", sdisable, 0) +plugin_def("lib_polyhelp", "polygon helpers", sbuildin, 1) + +plugin_header("\nFeature plugins:\n") +plugin_def("acompnet", "net auto-completion", sdisable, 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("boardflip", "flip board objects", 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("extedit", "edit with external program", sbuildin, 1) +plugin_def("fontmode", "font editor", sbuildin, 1) +plugin_def("gpmi", "GPMI scripting", 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", sdisable, 0) +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("shand_cmd", "command shorthands", sbuildin, 1) +plugin_def("shape", "generate regular shapes", sbuildin, 1) +plugin_def("smartdisperse", "netlist based dispenser", sbuildin, 1) +plugin_def("stroke", "libstroke gestures", sdisable, 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_dsn", "specctra .dsn importer", sbuildin, 1) +plugin_def("import_edif", "import edif", sbuildin, 1) +plugin_def("import_hpgl", "import HP-GL plot files", 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("io_tedax", "tEDAx (Trivial EDA eXchange)", sbuildin, 1) + +plugin_header("\nExport plugins:\n") +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", sdisable, 0) +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", sdisable, 0) +plugin_def("export_lpr", "lpr pcb_exporter (printer)", sbuildin, 1) +plugin_def("export_nelma", "nelma pcb_exporter", sbuildin, 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_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_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_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_def("hid_srv_ws", "websocket server HID", sdisable, 0) + + +plugin_dep("draw_fab", "report") +plugin_dep("export_lpr", "export_ps") +plugin_dep("export_openscad", "lib_polyhelp") +plugin_dep("export_xy", "export_bom") +plugin_dep("extedit", "io_lihata") +plugin_dep("fp_wget", "fp_fs") +plugin_dep("hid_gtk2_gdk", "draw_csect") +plugin_dep("hid_gtk2_gdk", "draw_fontsel") +plugin_dep("hid_gtk2_gdk", "lib_gtk_common") +plugin_dep("hid_gtk2_gdk", "lib_gtk_config") +plugin_dep("hid_gtk2_gdk", "lib_gtk_hid") +plugin_dep("hid_gtk2_gl", "draw_csect") +plugin_dep("hid_gtk2_gl", "draw_fontsel") +plugin_dep("hid_gtk2_gl", "lib_gtk_common") +plugin_dep("hid_gtk2_gl", "lib_gtk_config") +plugin_dep("hid_gtk2_gl", "lib_gtk_hid") +plugin_dep("hid_gtk3_cairo", "draw_csect") +plugin_dep("hid_gtk3_cairo", "draw_fontsel") +plugin_dep("hid_gtk3_cairo", "lib_gtk_common") +plugin_dep("hid_gtk3_cairo", "lib_gtk_config") +plugin_dep("hid_gtk3_cairo", "lib_gtk_hid") +plugin_dep("hid_lesstif", "dialogs") +plugin_dep("hid_lesstif", "draw_csect") +plugin_dep("hid_lesstif", "draw_fontsel") +plugin_dep("hid_lesstif", "lib_hid_common") +plugin_dep("import_mentor_sch", "lib_gensexpr") +plugin_dep("io_autotrax", "boardflip") +plugin_dep("io_autotrax", "lib_polyhelp") +plugin_dep("io_eagle", "boardflip") +plugin_dep("io_hyp", "lib_netmap") +plugin_dep("io_hyp", "lib_padstack_hash") +plugin_dep("io_kicad", "lib_gensexpr") +plugin_dep("io_kicad_legacy", "io_kicad") +plugin_dep("io_pcb", "lib_compat_help") +plugin_dep("lib_gtk_common", "lib_gtk_config") +plugin_dep("lib_gtk_hid", "dialogs") +plugin_dep("lib_gtk_hid", "lib_hid_common") +plugin_dep("millpath", "lib_polyhelp") Index: tags/1.2.7/scconfig/revtest.c =================================================================== --- tags/1.2.7/scconfig/revtest.c (nonexistent) +++ tags/1.2.7/scconfig/revtest.c (revision 13657) @@ -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/1.2.7/scconfig/template/cdep.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/cdep.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/cdep.tmpasm (revision 13657) @@ -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/1.2.7/scconfig/template/comp_var.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/comp_var.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/comp_var.tmpasm (revision 13657) @@ -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/1.2.7/scconfig/template/compile.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/compile.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/compile.tmpasm (revision 13657) @@ -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/1.2.7/scconfig/template/debug.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/debug.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/debug.tmpasm (revision 13657) @@ -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/1.2.7/scconfig/template/plugin_conf.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/plugin_conf.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/plugin_conf.tmpasm (revision 13657) @@ -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/1.2.7/scconfig/template/plugin_sphash.tmpasm =================================================================== --- tags/1.2.7/scconfig/template/plugin_sphash.tmpasm (nonexistent) +++ tags/1.2.7/scconfig/template/plugin_sphash.tmpasm (revision 13657) @@ -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/1.2.7/scconfig =================================================================== --- tags/1.2.7/scconfig (nonexistent) +++ tags/1.2.7/scconfig (revision 13657) Property changes on: tags/1.2.7/scconfig ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## +svn://repo.hu/scconfig/trunk/src src Index: tags/1.2.7/src/Makefile.dep =================================================================== --- tags/1.2.7/src/Makefile.dep (nonexistent) +++ tags/1.2.7/src/Makefile.dep (revision 13657) @@ -0,0 +1,7581 @@ +### Generated file, do not edit, run make dep ### + +../src_plugins/acompnet/acompnet.o: ../src_plugins/acompnet/acompnet.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h layer_ui.h action_helper.h hid_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 conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 compat_misc.h error.h obj_all.h dolists.h +../src_plugins/autocrop/autocrop.o: ../src_plugins/autocrop/autocrop.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 move.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 obj_all.h box.h hid_actions.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 hid_actions.h hid.h error.h drc.h \ + global_typedefs.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_nls.h board.h const.h \ + vtroutestyle.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h library.h rats_patch.h board.h \ + event.h dolists.h +../src_plugins/autoplace/autoplace.o: \ + ../src_plugins/autoplace/autoplace.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h \ + ../src_plugins/autoplace/autoplace.h global_typedefs.h box.h \ + compat_misc.h compat_nls.h data.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.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 rats.h netlist.h \ + route_style.h remove.h rotate.h obj_pinvia.h obj_rat.h obj_term.h \ + ../src_3rd/genvector/vtp0.h data_it.h data.h +../src_plugins/autoroute/action.o: ../src_plugins/autoroute/action.c \ + ../config.h ../src_plugins/autoroute/autoroute.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h action_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 hid_actions.h hid.h \ + error.h drc.h event.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h macro.h \ + ../src_plugins/autoroute/autoroute.h board.h vtroutestyle.h library.h \ + rats_patch.h board.h box.h draw.h error.h find.h heap.h rtree.h \ + ../src_plugins/autoroute/mtspace.h ../src_plugins/autoroute/vector.h \ + polygon.h rats.h netlist.h route_style.h remove.h obj_pinvia_therm.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h pcb-printf.h layer.h \ + compat_nls.h obj_all.h obj_line_draw.h obj_pinvia_draw.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 \ + macro.h move.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + data_parent.h misc_util.h heap.h rtree.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/boardflip/boardflip.o: \ + ../src_plugins/boardflip/boardflip.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h rats.h netlist.h \ + route_style.h polygon.h rtree.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h ht_subc.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 obj_all.h \ + hid_actions.h compat_misc.h ../src_plugins/boardflip/boardflip.h unit.h \ + dolists.h +../src_plugins/diag/diag.o: ../src_plugins/diag/diag.c ../config.h \ + board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + flag_str.h layer.h ../src_plugins/diag/diag_conf.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 action_helper.h hid_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 rats.h netlist.h route_style.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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/dialogs.o: ../src_plugins/dialogs/dialogs.c \ + ../config.h hid.h error.h drc.h unit.h global_typedefs.h pcb_bool.h \ + attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h hid_attrib.h hid.h \ + hid_actions.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h action_helper.h \ + ../src_plugins/dialogs/dlg_test.c \ + ../src_plugins/dialogs/dlg_layer_binding.c board.h const.h \ + vtroutestyle.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h const.h \ + conf_core.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/genvector/vtp0.h list_conf.h \ + compat_misc.h obj_subc.h search.h rats.h netlist.h route_style.h \ + ../src_plugins/dialogs/dlg_flag_edit.c flag.h flag_str.h change.h \ + ../src_plugins/dialogs/dlg_padstack.c obj_pstk.h obj_pstk_inlines.h \ + data.h thermal.h dolists.h +../src_plugins/distalign/distalign.o: \ + ../src_plugins/distalign/distalign.c board.h ../config.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 rats.h \ + netlist.h route_style.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 action_helper.h \ + hid_actions.h compat_misc.h dolists.h +../src_plugins/distaligntext/distaligntext.o: \ + ../src_plugins/distaligntext/distaligntext.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 rats.h \ + netlist.h route_style.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 action_helper.h \ + hid_actions.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + box.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 hid_flags.h hid_actions.h \ + ../src_plugins/djopt/djopt_conf.h conf.h obj_line.h obj_pinvia.h event.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 \ + compat_misc.h hid_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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h build_run.h compat_misc.h \ + data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h draw.h \ + ../src_plugins/draw_fab/../report/drill.h obj_all.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 \ + ../src_plugins/draw_fab/draw_fab_conf.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 obj_pstk_inlines.h data.h thermal.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h build_run.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h draw.h font.h const.h hid_actions.h obj_all.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 \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 \ + obj_text.h obj_text_draw.h obj_line_draw.h +../src_plugins/export_bboard/bboard.o: \ + ../src_plugins/export_bboard/bboard.c ../config.h math_helper.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h buffer.h layer.h layer_grp.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 obj_all.h rtree.h hid.h hid_attrib.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h hid_helper.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 build_run.h board.h const.h \ + macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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_helper.h hid_init.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 const.h macro.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h board.h \ + data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h error.h rats.h netlist.h route_style.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 ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h hid.h hid_draw_helpers.h \ + hid_nogui.h hid_actions.h hid_init.h hid_attrib.h hid_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 obj_line.h \ + obj_pinvia.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.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 pcb-printf.h \ + compat_misc.h ../src_plugins/export_dxf/lht_template.h safe_fs.h hid.h \ + hid_nogui.h hid_draw_helpers.h hid_init.h hid_attrib.h hid_color.h \ + hid_helper.h hid_flags.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 ../src_3rd/genht/htsi.h \ + math_helper.h board.h const.h macro.h vtroutestyle.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 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_helper.h hid_flags.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 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 const.h \ + macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h error.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h rats.h netlist.h route_style.h \ + hid_helper.h layer.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 hid_init.h \ + hid_attrib.h hid_flags.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/gerber.o: \ + ../src_plugins/export_gerber/gerber.c ../config.h math_helper.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h build_run.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h error.h draw.h layer.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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_helper.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 \ + ../src_3rd/genvector/vtp0.h list_conf.h hid.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h hid_attrib.h hid_flags.h conf_core.h +../src_plugins/export_ipcd356/ipcd356.o: \ + ../src_plugins/export_ipcd356/ipcd356.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + rats.h netlist.h route_style.h error.h find.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h netlist.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 obj_pinvia.h compat_misc.h \ + safe_fs.h hid.h hid_nogui.h hid_helper.h hid_attrib.h hid_init.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/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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.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/genvector/gds_char.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 hid.h \ + ../src_plugins/export_lpr/../export_ps/ps.h hid_nogui.h hid_init.h \ + hid_attrib.h hid_actions.h +../src_plugins/export_nelma/nelma.o: ../src_plugins/export_nelma/nelma.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h rats.h netlist.h route_style.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_helper.h \ + safe_fs.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 hid.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h hid_attrib.h hid_flags.h hid_color.h \ + dolists.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 ../src_3rd/genvector/vti0.h \ + compat_misc.h board.h const.h macro.h vtroutestyle.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h layer.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 hid.h hid_nogui.h hid_draw_helpers.h \ + hid_init.h hid_actions.h hid_attrib.h hid_color.h hid_helper.h \ + hid_flags.h ../src_plugins/export_openscad/scad_draw.c \ + ../src_plugins/export_openscad/../lib_polyhelp/topoly.h obj_common.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h error.h layer.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 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_helper.h hid_flags.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer.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 hid_attrib.h hid_helper.h \ + hid_flags.h hid_color.h +../src_plugins/export_ps/ps.o: ../src_plugins/export_ps/ps.c ../config.h \ + math_helper.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h error.h draw.h pcb-printf.h ../src_3rd/genvector/gds_char.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_helper.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 \ + hid.h hid_nogui.h hid_draw_helpers.h ../src_plugins/export_ps/ps.h \ + hid_init.h hid_attrib.h hid_flags.h hid_actions.h conf_core.h \ + compat_misc.h compat_nls.h stub_draw.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 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_helper.h hid_flags.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h layer.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 hid.h hid_nogui.h hid_draw_helpers.h \ + hid_init.h hid_attrib.h hid_color.h hid_helper.h hid_flags.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 build_run.h board.h const.h \ + macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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_helper.h hid_init.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 math_helper.h build_run.h \ + board.h const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 obj_pinvia.h netlist.h \ + route_style.h safe_fs.h hid.h hid_nogui.h hid_attrib.h hid_helper.h \ + hid_init.h ../src_plugins/export_xy/default_templ.h +../src_plugins/extedit/extedit.o: ../src_plugins/extedit/extedit.c \ + ../config.h hid.h error.h drc.h unit.h global_typedefs.h pcb_bool.h \ + attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h hid_attrib.h hid.h \ + hid_actions.h hid_dad.h compat_misc.h hid_attrib.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h action_helper.h board.h const.h \ + vtroutestyle.h library.h rats_patch.h board.h compat_fs.h compat_misc.h \ + const.h conf_core.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/genvector/vtp0.h list_conf.h data.h crosshair.h vtonpoint.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h buffer.h paths.h remove.h \ + safe_fs.h search.h rats.h netlist.h route_style.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 ../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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 hid_actions.h compat_misc.h event.h polygon.h \ + obj_poly_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 board.h const.h macro.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h board.h \ + buffer.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h error.h obj_elem.h obj_elem_list.h \ + obj_elem_op.h operation.h compat_misc.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h operation.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 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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h paths.h \ + ../src_3rd/genvector/gds_char.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 compat_fs.h \ + compat_misc.h error.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 compat_nls.h macro.h safe_fs.h compat_inc.h +../src_plugins/fp_wget/edakrill.o: ../src_plugins/fp_wget/edakrill.c \ + ../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 ../config.h \ + ../src_plugins/fp_wget/wget_common.h ../src_plugins/fp_wget/edakrill.h \ + plug_footprint.h vtlibrary.h ../src_plugins/fp_wget/fp_wget_conf.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/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 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 +../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 \ + ../src_plugins/fp_wget/fp_wget_conf.h conf.h global_typedefs.h \ + pcb_bool.h unit.h pcb-printf.h ../src_3rd/genvector/gds_char.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/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/fp_wget_conf_fields.h +../src_plugins/fp_wget/gedasymbols.o: \ + ../src_plugins/fp_wget/gedasymbols.c ../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 ../config.h \ + ../src_plugins/fp_wget/wget_common.h \ + ../src_plugins/fp_wget/gedasymbols.h plug_footprint.h vtlibrary.h \ + ../src_plugins/fp_wget/fp_wget_conf.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/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 \ + 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 +../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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h hid.h error.h drc.h data.h \ + crosshair.h vtonpoint.h hid.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h pcb-printf.h ../src_3rd/genvector/gds_char.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 \ + hid_draw_helpers.h hid_nogui.h hid_actions.h hid_init.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 crosshair.h vtonpoint.h \ + hid.h error.h drc.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h \ + const.h clip.h data.h crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h hid_draw_helpers.h \ + hid_attrib.h hid_helper.h hid_color.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 \ + ../src_3rd/genht/htpp.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_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h library.h rats_patch.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_config/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h +../src_plugins/hid_gtk2_gdk/gtkhid-main.o: \ + ../src_plugins/hid_gtk2_gdk/gtkhid-main.c ../config.h action_helper.h \ + global_typedefs.h pcb_bool.h unit.h error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 \ + error.h drc.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genht/htsp.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_config/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h const.h library.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/draw_gl.o: \ + ../src_plugins/hid_gtk2_gl/draw_gl.c \ + ../src_plugins/hid_gtk2_gl/stencil_gl.h \ + ../src_plugins/hid_gtk2_gl/opengl.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 error.h drc.h attrib.h \ + layer.h globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h const.h \ + clip.h data.h crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h \ + hid_draw_helpers.h hid_attrib.h hid_helper.h hid_color.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 ../src_plugins/lib_gtk_config/lib_gtk_config.h hid.h event.h \ + conf_hid.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h library.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/hid_gtk2_gl/opengl.h ../src_plugins/hid_gtk2_gl/draw_gl.h \ + ../src_plugins/hid_gtk2_gl/hidgl.h \ + ../src_plugins/hid_gtk2_gl/stencil_gl.h +../src_plugins/hid_gtk2_gl/gtkhid-main.o: \ + ../src_plugins/hid_gtk2_gl/gtkhid-main.c ../config.h action_helper.h \ + global_typedefs.h pcb_bool.h unit.h error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 \ + error.h drc.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genht/htsp.h ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/hid_gtk2_gl/draw_gl.h ../src_plugins/hid_gtk2_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_config/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h const.h library.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/hidgl.o: ../src_plugins/hid_gtk2_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 crosshair.h vtonpoint.h \ + hid.h error.h drc.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h \ + const.h clip.h data.h crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h hid_draw_helpers.h hid_attrib.h \ + hid_helper.h hid_color.h ../src_plugins/lib_gtk_config/hid_gtk_conf.h \ + conf.h ../src_plugins/lib_gtk_config/lib_gtk_config.h hid.h event.h \ + conf_hid.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/hid_gtk2_gl/opengl.h action_helper.h error.h \ + ../src_plugins/hid_gtk2_gl/hidgl.h ../src_plugins/hid_gtk2_gl/draw_gl.h \ + rtree.h ../src_plugins/hid_gtk2_gl/stencil_gl.h +../src_plugins/hid_gtk2_gl/stencil_gl.o: \ + ../src_plugins/hid_gtk2_gl/stencil_gl.c \ + ../src_plugins/hid_gtk2_gl/stencil_gl.h \ + ../src_plugins/hid_gtk2_gl/opengl.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 crosshair.h vtonpoint.h \ + hid.h error.h drc.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h \ + const.h clip.h data.h crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h hid_draw_helpers.h \ + hid_attrib.h hid_helper.h hid_color.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 \ + ../src_3rd/genht/htpp.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_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h library.h rats_patch.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_config/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h +../src_plugins/hid_gtk3_cairo/gtkhid-main.o: \ + ../src_plugins/hid_gtk3_cairo/gtkhid-main.c ../config.h action_helper.h \ + global_typedefs.h pcb_bool.h unit.h error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 \ + error.h drc.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genht/htsp.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_config/lib_gtk_config.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h board.h const.h library.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/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 compat_misc.h data.h layer.h \ + attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h layer_grp.h route.h const.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h build_run.h \ + crosshair.h layer.h pcb-printf.h hid.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + ../src_3rd/genht/htpp.h hid_cfg.h compat_nls.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h hid_attrib.h hid_actions.h hid_init.h \ + ../src_plugins/hid_lesstif/stdarg.h misc_util.h search.h rats.h \ + netlist.h route_style.h action_helper.h change.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 compat_misc.h data.h layer.h \ + attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h layer_grp.h route.h const.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h buffer.h \ + plug_footprint.h vtlibrary.h hid.h ../src_plugins/hid_lesstif/lesstif.h \ + hid_cfg_input.h ../src_3rd/genht/htpp.h hid_cfg.h compat_nls.h board.h \ + vtroutestyle.h library.h rats_patch.h board.h \ + ../src_plugins/hid_lesstif/stdarg.h event.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h action_helper.h crosshair.h \ + layer.h pcb-printf.h clip.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 safe_fs.h hid.h \ + hid_nogui.h hid_draw_helpers.h hid_cfg.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + ../src_3rd/genht/htpp.h hid_cfg.h compat_nls.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h hid_attrib.h hid_helper.h hid_init.h \ + hid_color.h hid_extents.h hid_flags.h hid_actions.h \ + ../src_plugins/hid_lesstif/stdarg.h misc_util.h compat_misc.h \ + layer_vis.h ../src_plugins/hid_lesstif/dlg_preview.c stub_draw.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 \ + ../src_3rd/genht/htpp.h ../src_plugins/hid_lesstif/lesstif.h \ + compat_nls.h board.h vtroutestyle.h library.h rats_patch.h board.h \ + paths.h hid_actions.h hid_flags.h ../src_plugins/hid_lesstif/stdarg.h \ + event.h compat_misc.h layer_vis.h +../src_plugins/hid_lesstif/menu_lht.o: \ + ../src_plugins/hid_lesstif/menu_lht.c +../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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h \ + rats.h netlist.h library.h route_style.h vtroutestyle.h select.h \ + operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h remove.h \ + crosshair.h draw.h obj_all.h event.h hid.h hid_actions.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/htpp.h hid_cfg.h \ + compat_nls.h board.h rats_patch.h board.h \ + ../src_plugins/hid_lesstif/stdarg.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 +../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 compat_misc.h data.h layer.h \ + attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h layer_grp.h route.h const.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h pcb-printf.h \ + hid.h ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + ../src_3rd/genht/htpp.h hid_cfg.h compat_nls.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h hid_flags.h \ + ../src_plugins/hid_lesstif/stdarg.h misc_util.h event.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 obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h layer.h +../src_plugins/hid_remote/remote.o: ../src_plugins/hid_remote/remote.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h hid.h error.h drc.h data.h \ + crosshair.h vtonpoint.h hid.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h pcb-printf.h ../src_3rd/genvector/gds_char.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 \ + ../src_plugins/hid_remote/proto.h hid_draw_helpers.h hid_nogui.h \ + hid_actions.h hid_init.h dolists.h +../src_plugins/hid_srv_ws/c2s.o: ../src_plugins/hid_srv_ws/c2s.c \ + ../config.h error.h ../src_plugins/hid_srv_ws/server.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h \ + ../src_plugins/hid_srv_ws/c2s.h +../src_plugins/hid_srv_ws/server.o: ../src_plugins/hid_srv_ws/server.c \ + ../config.h ../src_3rd/genht/hash.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 ../src_plugins/hid_srv_ws/server.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h \ + ../src_plugins/hid_srv_ws/c2s.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + polygon.h safe_fs.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 action_helper.h hid_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 dolists.h +../src_plugins/import_edif/edif.o: ../src_plugins/import_edif/edif.c \ + math_helper.h board.h ../config.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + library.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 compat_misc.h compat_nls.h safe_fs.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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/import_edif/import_edif.o: \ + ../src_plugins/import_edif/import_edif.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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/genvector/gds_char.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 netlist.h route_style.h \ + rats_patch.h plug_io.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.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 action_helper.h \ + hid_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_ltspice/ltspice.o: \ + ../src_plugins/import_ltspice/ltspice.c ../config.h \ + ../src_3rd/qparse/qparse.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h pcb-printf.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/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + action_helper.h hid_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 \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h pcb-printf.h ../src_3rd/genvector/gds_char.h compat_misc.h \ + ../src_3rd/gensexpr/gsxl.h ../src_3rd/gensexpr/gensexpr_impl.h \ + ../src_3rd/gensexpr/gsx_parse.h action_helper.h hid_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 ../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 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 hid_actions.h \ + hid.h error.h drc.h global_typedefs.h pcb_bool.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.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 +../src_plugins/import_mucs/mucs.o: ../src_plugins/import_mucs/mucs.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h pcb-printf.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/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + action_helper.h hid_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 dolists.h +../src_plugins/import_netlist/import_netlist.o: \ + ../src_plugins/import_netlist/import_netlist.c ../config.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.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/genvector/gds_char.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 \ + plug_import.h conf_core.h error.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h rats_patch.h compat_misc.h \ + compat_nls.h paths.h safe_fs.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h action_helper.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 rats.h netlist.h route_style.h hid_actions.h \ + ../src_plugins/import_sch/import_sch_conf.h conf.h misc_util.h \ + compat_nls.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h pcb-printf.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/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + action_helper.h hid_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/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 library.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 obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h layer_grp.h route.h const.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/read.h hid_actions.h board.h vtroutestyle.h \ + rats_patch.h board.h netlist.h route_style.h conf_core.h buffer.h hid.h \ + action_helper.h compat_misc.h dolists.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/read.h layer.h const.h netlist.h \ + route_style.h polygon.h misc_util.h conf_core.h move.h macro.h obj_all.h \ + safe_fs.h rotate.h ../src_plugins/boardflip/boardflip.h unit.h \ + hid_actions.h +../src_plugins/io_autotrax/write.o: ../src_plugins/io_autotrax/write.c \ + ../config.h compat_misc.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_autotrax/write.h layer.h const.h obj_all.h \ + polygon_offs.h ../src_plugins/io_autotrax/../lib_polyhelp/polyhelp.h \ + obj_poly.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 error.h drc.h unit.h global_typedefs.h \ + pcb_bool.h attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h plug_io.h library.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/genvector/vtp0.h list_conf.h ../src_plugins/io_eagle/read.h \ + board.h const.h vtroutestyle.h rats_patch.h board.h conf.h \ + ../src_plugins/io_eagle/read_dru.h hid_actions.h hid.h dolists.h +../src_plugins/io_eagle/read.o: ../src_plugins/io_eagle/read.c \ + ../config.h ../src_plugins/boardflip/boardflip.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h unit.h \ + board.h vtroutestyle.h library.h rats_patch.h board.h \ + ../src_plugins/io_eagle/read.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h polygon.h rtree.h hid_actions.h compat_misc.h \ + ../src_plugins/io_eagle/trparse.h ../src_plugins/io_eagle/trparse_xml.h \ + ../src_plugins/io_eagle/trparse_bin.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 library.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 safe_fs.h board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.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 action_helper.h global_typedefs.h pcb_bool.h unit.h \ + compat_nls.h hid.h error.h drc.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h hid_draw_helpers.h hid_nogui.h \ + hid_actions.h hid.h hid_init.h hid_attrib.h hid_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 event.h plug_io.h \ + library.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/genvector/vtp0.h list_conf.h ../src_plugins/io_hyp/parser.h \ + pcb_bool.h board.h const.h vtroutestyle.h rats_patch.h board.h \ + ../src_plugins/io_hyp/write.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.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 \ + ../src_3rd/genvector/gds_char.h obj_all.h flag_str.h polygon.h rtree.h \ + layer.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h search.h rats.h netlist.h route_style.h \ + rotate.h hid_actions.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 compat_misc.h safe_fs.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 library.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 const.h macro.h vtroutestyle.h \ + attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h rats_patch.h \ + board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + compat_misc.h polygon.h ../src_plugins/lib_padstack_hash/padstack_hash.h \ + ../src_3rd/genht/htpp.h obj_pad.h obj_pinvia.h \ + ../src_plugins/lib_netmap/netmap.h library.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 library.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 obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h layer_grp.h route.h const.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.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 \ + hid_actions.h dolists.h +../src_plugins/io_kicad/read.o: ../src_plugins/io_kicad/read.c \ + ../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 compat_misc.h ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad/read.h layer.h const.h netlist.h route_style.h \ + polygon.h misc_util.h conf_core.h move.h macro.h obj_all.h rotate.h \ + safe_fs.h attrib.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 board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + error.h pcb-printf.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/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genvector/vtp0.h list_conf.h \ + action_helper.h hid_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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h \ + ../src_plugins/io_kicad/uniq_name.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad/write.h layer.h const.h netlist.h route_style.h \ + obj_all.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 library.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 obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h layer_grp.h route.h const.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.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 \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.h \ + ../src_plugins/io_kicad_legacy/../io_kicad/uniq_name.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_kicad_legacy/write.h layer.h const.h netlist.h \ + route_style.h obj_all.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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h macro.h \ + ../src_plugins/io_lihata/common.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 library.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h rtree.h ht_subc.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/genvector/gds_char.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.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_all.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 vtpadstack.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h rtree.h ht_subc.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/genvector/gds_char.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/genvector/vtp0.h list_conf.h \ + flag_str.h compat_misc.h rats_patch.h hid_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 +../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 library.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 \ + hid_actions.h hid.h error.h drc.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 const.h macro.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.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/genht/htsp.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 const.h macro.h vtroutestyle.h \ + attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.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 buffer.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h attrib.h \ + data_parent.h change.h board.h const.h macro.h vtroutestyle.h layer.h \ + obj_all_list.h obj_arc_list.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h data.h \ + crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 move.h \ + ../src_plugins/io_pcb/parse_common.h pcb-printf.h polygon.h rats.h \ + netlist.h route_style.h remove.h flag_str.h compat_fs.h compat_misc.h \ + paths.h rats_patch.h hid_actions.h hid_flags.h \ + ../src_plugins/io_pcb/attribs.h route_style.h obj_poly.h \ + ../src_plugins/lib_compat_help/layer_compat.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 \ + library.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 \ + const.h macro.h vtroutestyle.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.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 flag_str.h flag.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h data_parent.h obj_arc.h obj_elem_list.h \ + obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h \ + obj_pinvia_list.h obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + obj_poly.h polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h \ + const.h data.h crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + ../src_plugins/io_pcb/file.h board.h vtroutestyle.h library.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 \ + ../src_plugins/io_pcb/attribs.h compat_misc.h compat_nls.h compat_cc.h \ + obj_common.h paths.h safe_fs.h +../src_plugins/io_pcb/parse_y.o: ../src_plugins/io_pcb/parse_y.c \ + ../config.h flag.h globalconst.h board.h const.h macro.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 layer.h \ + data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.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 obj_all.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h \ + vtonpoint.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/io_tedax/parse.h unit.h error.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h pcb-printf.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/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h obj_elem.h obj_line.h obj_arc.h \ + obj_pad.h obj_pinvia.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h board.h \ + vtroutestyle.h library.h rats_patch.h board.h \ + ../src_plugins/io_tedax/netlist.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + 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 hid_actions.h \ + action_helper.h compat_misc.h dolists.h +../src_plugins/io_tedax/netlist.o: ../src_plugins/io_tedax/netlist.c \ + ../config.h ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h \ + ../src_3rd/genht/hash.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h error.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h compat_misc.h hid_actions.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 \ + ../src_plugins/io_tedax/parse.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/jostle/jostle.o: ../src_plugins/jostle/jostle.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 rats.h \ + netlist.h route_style.h polygon.h remove.h error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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_actions.h layer.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 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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h ../src_plugins/lib_compat_help/pstk_compat.h \ + obj_pstk.h layer.h obj_pstk_shape.h polygon.h rtree.h vtpadstack_t.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h board.h const.h vtroutestyle.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + ht_subc.h vtpadstack.h obj_pinvia.h \ + ../src_plugins/lib_compat_help/pstk_compat.c obj_pstk_inlines.h data.h \ + thermal.h compat_misc.h +../src_plugins/lib_gensexpr/lib_gensexpr.o: \ + ../src_plugins/lib_gensexpr/lib_gensexpr.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_gtk_common/act_fileio.o: \ + ../src_plugins/lib_gtk_common/act_fileio.c ../config.h \ + ../src_plugins/lib_gtk_common/act_fileio.h unit.h hid_actions.h hid.h \ + error.h drc.h unit.h global_typedefs.h pcb_bool.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h conf_core.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/genvector/vtp0.h list_conf.h compat_nls.h plug_footprint.h \ + vtlibrary.h compat_misc.h board.h const.h vtroutestyle.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/lib_gtk_common/dlg_file_chooser.h plug_io.h \ + ../src_plugins/lib_gtk_common/util_str.h +../src_plugins/lib_gtk_common/act_print.o: \ + ../src_plugins/lib_gtk_common/act_print.c ../config.h \ + ../src_plugins/lib_gtk_common/act_print.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h hid.h error.h drc.h \ + hid_init.h hid.h hid_attrib.h data.h crosshair.h vtonpoint.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h compat_nls.h \ + ../src_plugins/lib_gtk_common/dlg_print.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_check_button.o: \ + ../src_plugins/lib_gtk_common/bu_check_button.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_check_button.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 hid_actions.h hid.h error.h \ + drc.h attrib.h layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h crosshair.h \ + vtonpoint.h route.h const.h misc_util.h compat_nls.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h library.h search.h rats.h netlist.h library.h \ + route_style.h vtroutestyle.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h layer_grp.h const.h \ + find.h board.h const.h rats_patch.h board.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + obj_subc_parent.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h +../src_plugins/lib_gtk_common/bu_entry.o: \ + ../src_plugins/lib_gtk_common/bu_entry.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_entry.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h unit.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 \ + ../src_plugins/lib_gtk_common/compat.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 compat_nls.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h pcb-printf.h ../src_3rd/genvector/gds_char.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_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 error.h drc.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 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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/bu_mode_btn.data const.h crosshair.h \ + vtonpoint.h hid.h route.h const.h conf_core.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h +../src_plugins/lib_gtk_common/bu_notebook.o: \ + ../src_plugins/lib_gtk_common/bu_notebook.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_notebook.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/compat.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 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 compat_misc.h compat_nls.h \ + board.h const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h +../src_plugins/lib_gtk_common/bu_text_view.o: \ + ../src_plugins/lib_gtk_common/bu_text_view.c ../config.h \ + ../src_plugins/lib_gtk_common/bu_text_view.h +../src_plugins/lib_gtk_common/dlg_about.o: \ + ../src_plugins/lib_gtk_common/dlg_about.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_about.h compat_nls.h build_run.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_report.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 \ + ../src_plugins/lib_gtk_common/dlg_attribute.h hid.h error.h drc.h \ + attrib.h layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + hid_attrib.h hid.h hid_init.h misc_util.h compat_misc.h compat_nls.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_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 \ + ../src_plugins/lib_gtk_common/dlg_attributes.h hid.h error.h drc.h \ + attrib.h layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + hid_attrib.h hid.h hid_init.h misc_util.h compat_misc.h compat_nls.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_command.o: \ + ../src_plugins/lib_gtk_common/dlg_command.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_command.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h board.h const.h \ + vtroutestyle.h library.h rats_patch.h board.h crosshair.h vtonpoint.h \ + hid.h route.h hid_actions.h compat_nls.h \ + ../src_plugins/lib_gtk_common/bu_text_view.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h +../src_plugins/lib_gtk_common/dlg_confirm.o: \ + ../src_plugins/lib_gtk_common/dlg_confirm.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_confirm.h compat_nls.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h hid_actions.h hid.h error.h \ + drc.h ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_message.h +../src_plugins/lib_gtk_common/dlg_drc.o: \ + ../src_plugins/lib_gtk_common/dlg_drc.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h error.h search.h rats.h \ + netlist.h route_style.h draw.h layer.h pcb-printf.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h hid_actions.h compat_nls.h \ + obj_all.h obj_pinvia_draw.h obj_pad_draw.h obj_rat_draw.h \ + obj_line_draw.h obj_arc_draw.h obj_poly_draw.h layer_vis.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h +../src_plugins/lib_gtk_common/dlg_export.o: \ + ../src_plugins/lib_gtk_common/dlg_export.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 \ + ../src_plugins/lib_gtk_common/dlg_export.h hid.h error.h drc.h attrib.h \ + layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_print.h pcb-printf.h hid_attrib.h \ + hid.h hid_init.h misc_util.h compat_misc.h compat_nls.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/dlg_file_chooser.o: \ + ../src_plugins/lib_gtk_common/dlg_file_chooser.c ../config.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h hid.h error.h drc.h \ + compat_misc.h ../src_plugins/lib_gtk_common/dlg_file_chooser.h \ + compat_nls.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/dlg_fontsel.o: \ + ../src_plugins/lib_gtk_common/dlg_fontsel.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_fontsel.h global_typedefs.h pcb_bool.h \ + unit.h hid.h error.h drc.h global_typedefs.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/bu_box.h layer.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h stub_draw.h hid.h const.h +../src_plugins/lib_gtk_common/dlg_input.o: \ + ../src_plugins/lib_gtk_common/dlg_input.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_input.h \ + ../src_plugins/lib_gtk_common/compat.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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h buffer.h data.h \ + crosshair.h vtonpoint.h hid.h route.h const.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h const.h \ + plug_footprint.h vtlibrary.h compat_nls.h compat_misc.h hid_actions.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.h layer.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_config/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 error.h drc.h unit.h global_typedefs.h pcb_bool.h \ + attrib.h layer.h globalconst.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h compat_misc.h \ + safe_fs.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/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/dlg_library_param.h plug_footprint.h \ + vtlibrary.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_log.o: \ + ../src_plugins/lib_gtk_common/dlg_log.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_log.h pcb_bool.h error.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 conf_hid.h error.h \ + pcb-printf.h hid_actions.h hid.h drc.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_nls.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/bu_text_view.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h conf.h +../src_plugins/lib_gtk_common/dlg_message.o: \ + ../src_plugins/lib_gtk_common/dlg_message.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_message.h compat_nls.h +../src_plugins/lib_gtk_common/dlg_netlist.o: \ + ../src_plugins/lib_gtk_common/dlg_netlist.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_netlist.h pcb_bool.h unit.h event.h \ + unit.h ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h board.h const.h \ + vtroutestyle.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h error.h macro.h const.h \ + find.h rats.h netlist.h route_style.h remove.h search.h rats.h select.h \ + operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h hid_actions.h \ + compat_nls.h obj_all.h ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/bu_text_view.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/bu_check_button.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h +../src_plugins/lib_gtk_common/dlg_pinout.o: \ + ../src_plugins/lib_gtk_common/dlg_pinout.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_pinout.h obj_elem.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h hid.h error.h drc.h layer.h \ + obj_all_list.h obj_elem_list.h obj_elem.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h conf_core.h copy.h data.h \ + crosshair.h vtonpoint.h hid.h route.h const.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h move.h \ + rotate.h macro.h ../src_plugins/lib_gtk_common/wt_preview.h layer.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/win_place.h +../src_plugins/lib_gtk_common/dlg_print.o: \ + ../src_plugins/lib_gtk_common/dlg_print.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 \ + ../src_plugins/lib_gtk_common/dlg_print.h hid.h error.h drc.h attrib.h \ + layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + hid_attrib.h hid.h hid_init.h misc_util.h compat_misc.h compat_nls.h \ + ../src_plugins/lib_gtk_common/dlg_attribute.h +../src_plugins/lib_gtk_common/dlg_progress.o: \ + ../src_plugins/lib_gtk_common/dlg_progress.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_progress.h pcb_bool.h compat_nls.h \ + ../src_plugins/lib_gtk_common/compat.h +../src_plugins/lib_gtk_common/dlg_propedit.o: \ + ../src_plugins/lib_gtk_common/dlg_propedit.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h compat_misc.h compat_nls.h \ + polygon.h rtree.h obj_all.h board.h const.h vtroutestyle.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h buffer.h draw.h ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.h layer.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h +../src_plugins/lib_gtk_common/dlg_report.o: \ + ../src_plugins/lib_gtk_common/dlg_report.c ../config.h \ + ../src_plugins/lib_gtk_common/dlg_report.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/bu_box.h +../src_plugins/lib_gtk_common/dlg_route_style.o: \ + ../src_plugins/lib_gtk_common/dlg_route_style.c ../config.h \ + compat_misc.h compat_nls.h polygon.h flag.h globalconst.h rtree.h \ + global_typedefs.h pcb_bool.h unit.h math_helper.h polyarea.h obj_all.h \ + obj_arc.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h attrib.h data_parent.h obj_elem.h \ + obj_arc_list.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_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h obj_poly_list.h box.h macro.h move.h \ + misc_util.h obj_rat.h ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/compat.h board.h const.h vtroutestyle.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h obj_all_list.h \ + obj_elem_list.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h layer_grp.h library.h \ + rats_patch.h board.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 error.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 drc.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 hid_actions.h hid.h \ + error.h drc.h unit.h global_typedefs.h pcb_bool.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_nls.h misc_util.h \ + pcb-printf.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/genht/htsp.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 ../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 unit.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + global_typedefs.h pcb_bool.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h conf_core.h \ + board.h const.h library.h rats_patch.h board.h crosshair.h vtonpoint.h \ + hid.h route.h pcb-printf.h hid_actions.h action_helper.h compat_nls.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/dlg_fontsel.h global_typedefs.h \ + ../src_plugins/lib_gtk_common/util_str.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 \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h event.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_config/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 ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.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 ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h const.h board.h const.h \ + vtroutestyle.h library.h rats_patch.h board.h action_helper.h \ + crosshair.h vtonpoint.h hid.h route.h conf_core.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h \ + ../src_plugins/lib_gtk_common/in_keyboard.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.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 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/menu_lht.o: \ + ../src_plugins/lib_gtk_common/menu_lht.c +../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 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/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/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_config/hid_gtk_conf.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 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/htsp.h \ + ../src_3rd/genht/ht.h ../src_3rd/genht/htip.h ../src_3rd/genht/htpp.h \ + hid_cfg.h ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h action_helper.h error.h \ + conf_core.h board.h const.h vtroutestyle.h library.h rats_patch.h \ + board.h compat_misc.h compat_nls.h draw.h hid.h data.h crosshair.h \ + vtonpoint.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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_gtk_common/util_block_hook.o: \ + ../src_plugins/lib_gtk_common/util_block_hook.c ../config.h \ + ../src_plugins/lib_gtk_common/util_block_hook.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.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 error.h \ + drc.h unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h hid_actions.h hid.h compat_misc.h +../src_plugins/lib_gtk_common/util_str.o: \ + ../src_plugins/lib_gtk_common/util_str.c ../config.h \ + ../src_plugins/lib_gtk_common/util_str.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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/glue.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/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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h \ + ../src_plugins/lib_gtk_common/glue.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/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 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 +../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 compat_nls.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 compat_nls.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h layer.h layer_ui.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer_vis.h board.h const.h \ + vtroutestyle.h layer_grp.h library.h rats_patch.h board.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h \ + polygon.h vtpadstack_t.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + hid_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 \ + ../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 \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h attrib.h \ + layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.h layer.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h copy.h \ + board.h const.h vtroutestyle.h library.h rats_patch.h board.h data.h \ + crosshair.h vtonpoint.h hid.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h move.h \ + rotate.h obj_all.h macro.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 \ + ../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 drc.h layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h pcb-printf.h board.h const.h \ + library.h rats_patch.h board.h compat_nls.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h +../src_plugins/lib_gtk_config/gtk_conf_list.o: \ + ../src_plugins/lib_gtk_config/gtk_conf_list.c ../config.h \ + ../src_plugins/lib_gtk_config/gtk_conf_list.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 compat_misc.h \ + ../src_plugins/lib_gtk_config/../lib_gtk_common/compat.h +../src_plugins/lib_gtk_config/gui-config.o: \ + ../src_plugins/lib_gtk_config/gui-config.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 \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h hid.h error.h drc.h \ + attrib.h layer.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h event.h conf_hid.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h board.h const.h vtroutestyle.h \ + library.h rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h layer.h action_helper.h \ + change.h plug_io.h error.h draw.h pcb-printf.h hid_attrib.h misc_util.h \ + paths.h plug_footprint.h vtlibrary.h stub_draw.h compat_misc.h \ + compat_nls.h fptr_cast.h safe_fs.h ../src_3rd/liblihata/tree.h \ + ../src_plugins/lib_gtk_config/gtk_conf_list.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_common/wt_preview.h obj_elem.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/bu_box.h \ + ../src_plugins/lib_gtk_common/bu_entry.h \ + ../src_plugins/lib_gtk_common/wt_coord_entry.h \ + ../src_plugins/lib_gtk_common/bu_notebook.h \ + ../src_plugins/lib_gtk_common/bu_text_view.h \ + ../src_plugins/lib_gtk_common/bu_check_button.h \ + ../src_plugins/lib_gtk_common/bu_status_line.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_common/bu_spin_button.h +../src_plugins/lib_gtk_config/lib_gtk_config.o: \ + ../src_plugins/lib_gtk_config/lib_gtk_config.c ../config.h \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h event.h conf_hid.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/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/glue.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_config/hid_gtk_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/lib_gtk_config/hid_gtk_conf_fields.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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.h \ + rats_patch.h board.h event.h ../src_plugins/lib_gtk_hid/render.h data.h \ + crosshair.h vtonpoint.h hid.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h search.h rats.h \ + netlist.h route_style.h change.h action_helper.h hid_attrib.h \ + hid_actions.h compat_nls.h compat_misc.h \ + ../src_plugins/lib_gtk_common/act_print.h \ + ../src_plugins/lib_gtk_common/act_fileio.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h \ + ../src_plugins/lib_gtk_common/dlg_route_style.h \ + ../src_plugins/lib_gtk_common/dlg_export.h \ + ../src_plugins/lib_gtk_common/dlg_library.h \ + ../src_plugins/lib_gtk_common/dlg_log.h error.h \ + ../src_plugins/lib_gtk_common/dlg_about.h \ + ../src_plugins/lib_gtk_common/dlg_netlist.h \ + ../src_plugins/lib_gtk_common/dlg_search.h \ + ../src_plugins/lib_gtk_common/dlg_fontsel.h global_typedefs.h \ + ../src_plugins/lib_gtk_config/lib_gtk_config.h \ + ../src_plugins/lib_gtk_hid/actions.h dolists.h +../src_plugins/lib_gtk_hid/common.o: ../src_plugins/lib_gtk_hid/common.c \ + ../config.h action_helper.h global_typedefs.h pcb_bool.h unit.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h error.h drc.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.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 \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.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_config/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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h action_helper.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 \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.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/bu_status_line.h \ + ../src_plugins/lib_gtk_config/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 conf_core.h globalconst.h \ + ../src_plugins/lib_gtk_hid/gui.h hid.h error.h drc.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.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 \ + ../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 ../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 attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h error.h drc.h \ + global_typedefs.h pcb_bool.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.h \ + rats_patch.h board.h ../src_plugins/lib_gtk_hid/render.h action_helper.h \ + conf_core.h ../src_plugins/lib_gtk_common/dlg_netlist.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_config/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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.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.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_confirm.h \ + ../src_plugins/lib_gtk_common/dlg_input.h \ + ../src_plugins/lib_gtk_common/dlg_log.h error.h \ + ../src_plugins/lib_gtk_common/dlg_file_chooser.h compat_nls.h plug_io.h \ + ../src_plugins/lib_gtk_common/util_str.h \ + ../src_plugins/lib_gtk_common/dlg_pinout.h obj_elem.h \ + ../src_plugins/lib_gtk_common/dlg_report.h \ + ../src_plugins/lib_gtk_common/dlg_progress.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/util_block_hook.h \ + ../src_plugins/lib_gtk_common/win_place.h \ + ../src_plugins/lib_gtk_config/hid_gtk_conf.h \ + ../src_plugins/lib_gtk_config/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 error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/htpp.h hid_cfg.h ../src_plugins/lib_gtk_common/glue.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/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/compat.h \ + ../src_plugins/lib_gtk_common/dlg_propedit.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/dlg_command.h \ + ../src_plugins/lib_gtk_common/wt_layersel.h layer_grp.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/in_mouse.h \ + ../src_plugins/lib_gtk_common/glue.h board.h const.h library.h \ + rats_patch.h board.h event.h ../src_plugins/lib_gtk_hid/render.h +../src_plugins/lib_hid_common/layer_menu.o: \ + ../src_plugins/lib_hid_common/layer_menu.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + hid.h layer.h layer_grp.h pcb-printf.h ../src_3rd/genvector/gds_char.h +../src_plugins/lib_hid_common/lib_hid_common.o: \ + ../src_plugins/lib_hid_common/lib_hid_common.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_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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h change.h board.h vtroutestyle.h library.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 ../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_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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h library.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h find.h \ + netlist.h route_style.h pcb-printf.h ../src_3rd/genvector/gds_char.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_padstack_hash/padstack_hash.o: \ + ../src_plugins/lib_padstack_hash/padstack_hash.c ../config.h \ + ../src_3rd/genht/htpp.h ../src_3rd/genht/ht.h \ + ../src_plugins/lib_padstack_hash/padstack_hash.h obj_pad.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + obj_pinvia.h obj_elem.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_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h \ + font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h macro.h move.h misc_util.h +../src_plugins/lib_polyhelp/polyhelp.o: \ + ../src_plugins/lib_polyhelp/polyhelp.c ../config.h \ + ../src_plugins/lib_polyhelp/polyhelp.h obj_poly.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + polyarea.h polygon.h rtree.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 macro.h move.h \ + misc_util.h polygon_offs.h ../src_plugins/lib_polyhelp/topoly.h board.h \ + const.h vtroutestyle.h layer.h obj_all_list.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_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h obj_poly_list.h box.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h board.h \ + obj_common.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h ht_subc.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 ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h \ + ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h hid_attrib.h \ + hid_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 const.h macro.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h board.h \ + obj_common.h error.h rtree.h obj_arc.h obj_line.h obj_poly.h \ + obj_poly_draw.h polygon.h rtree.h search.h rats.h netlist.h \ + route_style.h hid.h error.h drc.h +../src_plugins/loghid/hid-logger.o: ../src_plugins/loghid/hid-logger.c \ + ../config.h ../src_plugins/loghid/hid-logger.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h action_helper.h change.h \ + board.h vtroutestyle.h library.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 action_helper.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 hid_actions.h hid.h \ + error.h drc.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h ../src_plugins/millpath/toolpath.h \ + layer.h layer_grp.h polygon.h rtree.h board.h const.h vtroutestyle.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h library.h rats_patch.h board.h \ + data.h crosshair.h vtonpoint.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + ht_subc.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h layer.h polygon.h rtree.h board.h \ + const.h vtroutestyle.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h ht_subc.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 \ + ../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 const.h data.h globalconst.h global_typedefs.h pcb_bool.h \ + unit.h layer.h attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + error.h plug_io.h library.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + find.h polygon.h search.h rats.h netlist.h route_style.h vtroutestyle.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 compat_misc.h rats.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 stub_mincut.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h action_helper.h change.h \ + board.h vtroutestyle.h library.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_actions.h \ + plug_footprint.h vtlibrary.h dolists.h +../src_plugins/polycombine/polycombine.o: \ + ../src_plugins/polycombine/polycombine.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 hid_actions.h \ + obj_poly.h dolists.h +../src_plugins/polystitch/polystitch.o: \ + ../src_plugins/polystitch/polystitch.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 hid_actions.h \ + obj_poly.h obj_poly_draw.h dolists.h +../src_plugins/propedit/propedit.o: ../src_plugins/propedit/propedit.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_plugins/propedit/props.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/ht.h \ + ../src_plugins/propedit/propsel.h hid_actions.h hid.h error.h drc.h \ + global_typedefs.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h error.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/genht/ht.h ../src_plugins/propedit/propsel.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 hid.h error.h drc.h \ + global_typedefs.h attrib.h layer.h globalconst.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +../src_plugins/propedit/propsel.o: ../src_plugins/propedit/propsel.c \ + ../config.h const.h data.h globalconst.h global_typedefs.h pcb_bool.h \ + unit.h layer.h attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/propedit/props.h global_typedefs.h \ + ../src_plugins/propedit/propsel.h change.h board.h vtroutestyle.h \ + library.h rats_patch.h misc_util.h compat_misc.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h rotate.h obj_pstk_inlines.h \ + data.h thermal.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 hid_actions.h misc_util.h obj_all.h \ + compat_misc.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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/query/query_access.h ../src_plugins/query/query.h \ + obj_any.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 ../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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h layer_grp.h route.h const.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h change.h board.h vtroutestyle.h library.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 \ + hid_actions.h compat_misc.h ../src_plugins/query/query.h obj_any.h \ + ../src_3rd/genregex/regex_se.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h ../src_plugins/query/fields_sphash.h \ + fptr_cast.h +../src_plugins/query/query_access.o: ../src_plugins/query/query_access.c \ + ../config.h math_helper.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/query/query_access.h ../src_plugins/query/query.h \ + obj_any.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 ../src_plugins/query/query_exec.h \ + layer.h obj_pstk_inlines.h data.h thermal.h +../src_plugins/query/query_act.o: ../src_plugins/query/query_act.c \ + ../config.h ../src_plugins/query/query.h obj_any.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.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/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 ../src_plugins/query/query_y.h \ + ../src_plugins/query/query_exec.h const.h draw.h hid.h error.h drc.h \ + layer.h obj_all_list.h obj_arc_list.h obj_arc.h obj_elem_list.h \ + obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h \ + obj_pinvia_list.h obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + obj_poly.h polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h select.h \ + operation.h board.h const.h vtroutestyle.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h library.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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/query/query.h obj_any.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 \ + ../src_plugins/query/query_exec.h ../src_plugins/query/query_access.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.h +../src_plugins/query/query_l.o: ../src_plugins/query/query_l.c unit.h \ + ../config.h ../src_plugins/query/query.h obj_any.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.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/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 ../src_plugins/query/query_y.h \ + compat_misc.h layer.h obj_all_list.h obj_arc_list.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h +../src_plugins/query/query_y.o: ../src_plugins/query/query_y.c const.h \ + unit.h ../config.h ../src_plugins/query/query.h obj_any.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.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/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 ../src_plugins/query/query_l.h \ + compat_misc.h +../src_plugins/renumber/renumber.o: ../src_plugins/renumber/renumber.c \ + ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.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 hid_actions.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h compat_nls.h \ + netlist.h route_style.h safe_fs.h pcb-printf.h dolists.h +../src_plugins/renumber/renumberblock.o: \ + ../src_plugins/renumber/renumberblock.c ../config.h board.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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/genvector/gds_char.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/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 obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + ../src_plugins/report/drill.h macro.h obj_pinvia.h obj_pstk_inlines.h \ + board.h vtroutestyle.h library.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 \ + ../src_plugins/report/report.h math_helper.h crosshair.h vtonpoint.h \ + hid.h error.h drc.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h \ + const.h board.h vtroutestyle.h library.h rats_patch.h board.h data.h \ + crosshair.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h ../src_plugins/report/drill.h \ + error.h search.h rats.h netlist.h route_style.h rats.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 action_helper.h hid_actions.h misc_util.h \ + ../src_plugins/report/report_conf.h conf.h compat_misc.h compat_nls.h \ + layer.h obj_all.h obj_pstk.h obj_pstk_inlines.h data.h thermal.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 \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + data_list.h ../src_3rd/genvector/vtp0.h data.h error.h event.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h operation.h rotate.h draw.h \ + draw_wireframe.h crosshair.h obj_rat_draw.h obj_line_op.h operation.h \ + obj_line_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/genvector/gds_char.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/dom.h ../src_3rd/liblihata/lihata.h \ + ../src_3rd/liblihata/parser.h list_conf.h layer_grp.h \ + ../src_plugins/rubberband_orig/fgeometry.h obj_common.h search.h rats.h \ + netlist.h route_style.h polygon.h \ + ../src_plugins/rubberband_orig/rubberband_conf.h conf.h \ + ../src_plugins/rubberband_orig/rubberband_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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h build_run.h action_helper.h buffer.h \ + ../src_plugins/shand_cmd/command.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h error.h plug_io.h rats.h \ + netlist.h route_style.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_actions.h compat_misc.h misc_util.h \ + dolists.h +../src_plugins/shape/shape.o: ../src_plugins/shape/shape.c ../config.h \ + ../src_plugins/shape/shape.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + layer.h pcb_bool.h action_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 hid_actions.h buffer.h compat_misc.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 math_helper.h \ + obj_poly.h obj_poly_draw.h rotate.h ../src_plugins/shape/shape_dialog.c \ + hid_dad.h compat_misc.h hid_attrib.h dolists.h +../src_plugins/smartdisperse/smartdisperse.o: \ + ../src_plugins/smartdisperse/smartdisperse.c ../src_3rd/genht/htpi.h \ + ../src_3rd/genht/ht.h ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.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 rats.h netlist.h \ + route_style.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 action_helper.h hid_actions.h compat_nls.h \ + obj_subc.h dolists.h +../src_plugins/stroke/stroke.o: ../src_plugins/stroke/stroke.c \ + ../config.h math_helper.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 conf_core.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + crosshair.h stub_stroke.h rotate.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h undo_act.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 compat_nls.h +../src_plugins/teardrops/teardrops.o: \ + ../src_plugins/teardrops/teardrops.c ../config.h math_helper.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.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 hid_actions.h \ + obj_all.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 \ + ../src_3rd/genregex/regex_sei.h ../src_3rd/genregex/regex_templ.h \ + ../src_3rd/genregex/regex.h change.h board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h board.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 \ + ../src_plugins/vendordrill/vendor.h stub_vendor.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 action_helper.h \ + hid_flags.h hid_actions.h hid_cfg.h \ + ../src_plugins/vendordrill/vendor_conf.h conf.h compat_misc.h \ + compat_nls.h obj_pinvia.h event.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/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/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 +action_act.o: action_act.c ../config.h action_helper.h global_typedefs.h \ + pcb_bool.h unit.h hid_actions.h hid.h error.h drc.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h library.h compat_nls.h safe_fs.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/genvector/vtp0.h list_conf.h +action_helper.o: action_helper.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h change.h copy.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h find.h \ + insert.h remove.h rotate.h search.h rats.h netlist.h route_style.h \ + select.h operation.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + stub_stroke.h funchash_core.h funchash.h funchash_core_list.h \ + hid_actions.h compat_misc.h compat_nls.h event.h obj_pinvia_draw.h \ + obj_pad_draw.h obj_line_draw.h obj_arc_draw.h obj_elem_draw.h \ + obj_text_draw.h obj_rat_draw.h obj_poly_draw.h obj_pstk_draw.h tool.h +attrib.o: attrib.c ../config.h compat_misc.h attrib.h +board.o: board.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h \ + hid_actions.h paths.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + draw.h event.h safe_fs.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 \ + box.h math_helper.h macro.h move.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.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 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 conf_hid.h error.h \ + compat_misc.h hid_dad.h hid_attrib.h hid.h drc.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 action_helper.h buffer.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h attrib.h data_parent.h board.h const.h macro.h vtroutestyle.h \ + layer.h obj_all_list.h obj_arc_list.h obj_arc.h obj_elem_list.h \ + obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h \ + obj_pinvia_list.h obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + obj_poly.h polyarea.h obj_poly_list.h box.h math_helper.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + library.h rats_patch.h copy.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h plug_io.h rotate.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 compat_misc.h \ + compat_nls.h obj_all_op.h obj_arc_op.h obj_elem_op.h obj_line_op.h \ + obj_pad_op.h obj_pinvia_op.h obj_poly_op.h obj_text_op.h obj_rat_op.h \ + obj_subc_op.h obj_pstk_op.h event.h safe_fs.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h build_run.h hid_init.h hid.h error.h drc.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.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 hid_actions.h compat_nls.h obj_all_op.h obj_arc_op.h \ + obj_elem_op.h obj_line_op.h obj_pad_op.h obj_pinvia_op.h obj_poly_op.h \ + obj_text_op.h obj_rat_op.h obj_subc_op.h obj_pstk_op.h obj_subc_parent.h \ + obj_term.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 library.h rats_patch.h \ + action_helper.h hid_actions.h change.h draw.h search.h rats.h netlist.h \ + route_style.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h event.h \ + compat_misc.h compat_nls.h obj_rat_draw.h +clip.o: clip.c ../config.h clip.h global_typedefs.h pcb_bool.h unit.h +compat_fs.o: compat_fs.c ../config.h compat_inc.h compat_fs.h \ + compat_misc.h compat_nls.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 compat_misc.h +conf.o: conf.c ../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 \ + ../src_3rd/genht/ht.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 conf_hid.h \ + error.h hid_cfg.h misc_util.h paths.h compat_fs.h compat_misc.h \ + safe_fs.h ../src_3rd/genvector/genvector_impl.c +conf_act.o: conf_act.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 route_style.h error.h hid.h \ + drc.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 \ + 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 +conf_internal.o: conf_internal.c +copy.o: copy.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.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 obj_all_op.h obj_arc_op.h obj_elem_op.h obj_line_op.h \ + obj_pad_op.h obj_pinvia_op.h obj_poly_op.h obj_text_op.h obj_rat_op.h \ + obj_subc_op.h obj_pstk_op.h +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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h data.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h draw_wireframe.h search.h rats.h netlist.h route_style.h \ + hid_actions.h compat_misc.h compat_nls.h find.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h event.h action_helper.h \ + obj_line_draw.h obj_arc_draw.h obj_text_draw.h obj_pstk_draw.h \ + obj_arc_ui.h obj_all_op.h obj_arc_op.h operation.h obj_elem_op.h \ + obj_line_op.h obj_pad_op.h obj_pinvia_op.h obj_poly_op.h obj_text_op.h \ + obj_rat_op.h obj_subc_op.h tool.h +data.o: data.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + data_list.h ../src_3rd/genvector/vtp0.h list_common.h obj_all.h \ + layer_it.h operation.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h rotate.h stub_draw.h \ + obj_all.h layer_ui.h obj_pad_draw.h obj_pinvia_draw.h obj_pstk_draw.h \ + obj_elem_draw.h obj_line_draw.h obj_arc_draw.h obj_rat_draw.h \ + obj_poly_draw.h obj_text_draw.h draw_composite.c draw_ly_spec.c +error.o: error.c ../config.h data.h globalconst.h global_typedefs.h \ + pcb_bool.h unit.h layer.h attrib.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + plug_io.h library.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h conf_core.h +event.o: event.c ../config.h event.h unit.h error.h fptr_cast.h +file_act.o: file_act.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h build_run.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h plug_io.h plug_import.h remove.h draw.h find.h search.h \ + rats.h netlist.h route_style.h hid_actions.h compat_misc.h compat_nls.h \ + hid_init.h layer_vis.h safe_fs.h +find.o: find.c ../config.h const.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + macro.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h layer_grp.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + find.h search.h rats.h netlist.h library.h route_style.h vtroutestyle.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h plug_io.h hid_actions.h \ + compat_misc.h event.h layer_vis.h obj_all.h obj_text_draw.h find_geo.c \ + obj_arc_ui.h obj_pstk_inlines.h board.h rats_patch.h thermal.h \ + find_lookup.c compat_nls.h obj_subc_parent.h find_intconn.c find_drc.c \ + obj_arc_draw.h obj_pad_draw.h obj_rat_draw.h obj_line_draw.h \ + obj_elem_draw.h obj_poly_draw.h obj_pinvia_draw.h obj_pstk_draw.h \ + find_misc.c change.h find_clear.c find_debug.c find_print.c +find_act.o: find_act.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 data.h crosshair.h vtonpoint.h \ + hid.h error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h find.h compat_nls.h +flag.o: flag.c ../config.h flag.h globalconst.h operation.h \ + global_typedefs.h pcb_bool.h unit.h obj_all_op.h obj_arc_op.h \ + obj_elem_op.h obj_line_op.h obj_pad_op.h obj_pinvia_op.h obj_poly_op.h \ + obj_text_op.h obj_rat_op.h obj_subc_op.h +flag_str.o: flag_str.c ../config.h const.h flag_str.h flag.h \ + globalconst.h compat_misc.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 obj_common.h ../src_3rd/genlist/gendlist.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 macro.h move.h misc_util.h board.h const.h vtroutestyle.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h obj_all_list.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 error.h \ + plug_io.h paths.h compat_nls.h compat_misc.h event.h font_internal.c +font_act.o: font_act.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h hid.h error.h drc.h action_helper.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 \ + 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 +gui_act.o: gui_act.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h build_run.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h tool.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 \ + rats.h netlist.h route_style.h find.h stub_stroke.h hid_actions.h \ + hid_init.h compat_nls.h compat_misc.h event.h layer_vis.h hid_attrib.h \ + operation.h obj_subc_op.h obj_elem_draw.h obj_pinvia_draw.h \ + obj_pad_draw.h +heap.o: heap.c ../config.h heap.h +hid_actions.o: hid_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 ../src_3rd/genht/hash.h \ + error.h event.h hid_actions.h hid.h drc.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + compat_misc.h compat_nls.h +hid_attrib.o: hid_attrib.c ../config.h hid_attrib.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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_cfg.h \ + error.h paths.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h safe_fs.h conf.h \ + global_typedefs.h pcb_bool.h unit.h pcb-printf.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_misc.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 hid_actions.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.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 \ + hid_cfg_action.h error.h compat_misc.h event.h unit.h +hid_color.o: hid_color.c ../config.h hid_color.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_misc.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +hid_draw_helpers.o: hid_draw_helpers.c ../config.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h polygon.h rtree.h +hid_extents.o: hid_extents.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + hid_draw_helpers.h hid_extents.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 obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h board.h \ + vtroutestyle.h library.h rats_patch.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + hid_flags.h hid_actions.h +hid_helper.o: hid_helper.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + hid_helper.h hid_attrib.h compat_misc.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 +hid_init.o: hid_init.c ../config.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h hid_nogui.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_attrib.h \ + hid_init.h conf_core.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/genvector/vtp0.h list_conf.h compat_misc.h compat_inc.h +hid_nogui.o: hid_nogui.c ../config.h hid.h error.h drc.h unit.h \ + global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_misc.h compat_nls.h \ + conf_core.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/genvector/vtp0.h list_conf.h +ht_element.o: ht_element.c ../config.h obj_elem_list.h obj_elem.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h \ + font.h ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h ../src_3rd/genht/ht.c \ + ../src_3rd/genht/ht_inlines.h +ht_subc.o: ht_subc.c ../config.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h rtree.h ht_subc.h \ + ../src_3rd/genht/ht.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + ../src_3rd/genht/ht.c ../src_3rd/genht/ht_inlines.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.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 macro.h move.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h data_parent.h misc_util.h +layer.o: layer.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h event.h layer_ui.h layer_vis.h \ + obj_pstk_inlines.h thermal.h +layer_grp.o: layer_grp.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + compat_misc.h event.h +layer_ui.o: layer_ui.c ../config.h layer_ui.h layer.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h attrib.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h event.h \ + ../src_3rd/genvector/genvector_impl.c +layer_vis.o: layer_vis.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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_ui.h layer_vis.h event.h \ + compat_misc.h conf_hid.h +library.o: library.c ../config.h library.h global_typedefs.h pcb_bool.h \ + unit.h macro.h compat_misc.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 \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h brave.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/genht/htsp.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + 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 \ + flag_str.h plugins.h ../src_3rd/puplug/error.h plug_footprint.h \ + vtlibrary.h event.h funchash.h conf_core.h layer_vis.h pcb_minuid.h \ + tool.h hid_actions.h hid_init.h compat_misc.h compat_nls.h dolists.h \ + generated_lists.h +main_act.o: main_act.c ../config.h hid_actions.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h hid_init.h conf_core.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/genvector/vtp0.h list_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 +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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.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 event.h hid_actions.h compat_misc.h obj_all_op.h obj_arc_op.h \ + obj_elem_op.h obj_line_op.h obj_pad_op.h obj_pinvia_op.h obj_poly_op.h \ + obj_text_op.h obj_rat_op.h obj_subc_op.h obj_pstk_op.h +netlist.o: netlist.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h error.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 find.h rats.h netlist.h \ + route_style.h hid_actions.h hid.h drc.h compat_misc.h event.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 \ + action_helper.h global_typedefs.h pcb_bool.h unit.h data.h globalconst.h \ + layer.h attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h board.h \ + vtroutestyle.h library.h rats_patch.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + hid_actions.h compat_nls.h compat_misc.h netlist.h route_style.h +obj_any.o: obj_any.c ../config.h obj_any.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.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_arc.o: obj_arc.c ../config.h compat_nls.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h rotate.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h draw_wireframe.h \ + obj_arc_op.h operation.h obj_subc_parent.h draw.h obj_arc_draw.h +obj_arc_list.o: obj_arc_list.c obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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/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 error.h drc.h attrib.h \ + layer.h globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h const.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 flag_str.h flag.h const.h \ + error.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h attrib.h data_parent.h obj_arc_ui.h \ + crosshair.h vtonpoint.h hid.h drc.h layer.h obj_all_list.h \ + obj_arc_list.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h macro.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h route.h +obj_elem.o: obj_elem.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + list_common.h plug_io.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 compat_nls.h compat_misc.h rotate.h remove.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h obj_pinvia_op.h operation.h \ + obj_pad_op.h obj_pinvia_draw.h obj_pad_draw.h obj_line_draw.h \ + obj_arc_draw.h obj_elem_op.h draw.h obj_text_draw.h obj_elem_draw.h +obj_elem_list.o: obj_elem_list.c ../config.h obj_elem.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h obj_elem_list.h ht_element.h \ + ../src_3rd/genht/ht.h ../src_3rd/genlist/gentdlist_impl.c +obj_line.o: obj_line.c ../config.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h library.h global_typedefs.h pcb_bool.h unit.h board.h const.h \ + macro.h vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + search.h rats.h netlist.h route_style.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + compat_nls.h compat_misc.h rotate.h obj_line_op.h operation.h \ + obj_subc_parent.h draw.h draw_wireframe.h obj_line_draw.h obj_rat_draw.h \ + obj_pinvia_draw.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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h find.h +obj_line_list.o: obj_line_list.c obj_line_list.h obj_line.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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_pad.o: obj_pad.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h compat_misc.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 obj_pad_op.h operation.h draw.h \ + obj_text_draw.h obj_pad_draw.h +obj_pad_list.o: obj_pad_list.c obj_pad_list.h obj_pad.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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.o: obj_pinvia.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 \ + compat_nls.h compat_misc.h stub_vendor.h rotate.h obj_pinvia_op.h \ + operation.h obj_subc_parent.h draw.h obj_text_draw.h obj_pinvia_draw.h +obj_pinvia_list.o: obj_pinvia_list.c obj_pinvia_list.h obj_pinvia.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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 const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h polygon.h rtree.h obj_pinvia_therm.h +obj_poly.o: obj_poly.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + compat_nls.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + polygon_offs.h rotate.h search.h rats.h netlist.h route_style.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 obj_poly_op.h operation.h \ + obj_poly_draw.h obj_subc_parent.h draw.h +obj_poly_list.o: obj_poly_list.c obj_poly_list.h obj_poly.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h conf_core.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 data.h crosshair.h vtonpoint.h \ + hid.h error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 search.h rats.h netlist.h \ + route_style.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + obj_pstk_op.c rotate.h +obj_pstk_act.o: obj_pstk_act.c ../config.h obj_pstk.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h obj_all_list.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_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_text_list.h obj_rat_list.h \ + obj_rat.h obj_pstk_shape.h polygon.h rtree.h vtpadstack_t.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h obj_pstk_inlines.h board.h \ + const.h vtroutestyle.h layer_grp.h library.h rats_patch.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + ../src_3rd/genht/htsp.h ht_subc.h vtpadstack.h thermal.h action_helper.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 hid_actions.h +obj_pstk_list.o: obj_pstk_list.c obj_pstk_list.h obj_pstk.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h buffer.h compat_misc.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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_rat.o: obj_rat.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h obj_line_draw.h obj_rat_op.h \ + operation.h draw.h obj_rat_draw.h rats.h netlist.h route_style.h +obj_rat_list.o: obj_rat_list.c obj_rat_list.h obj_rat.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.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_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 \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + board.h const.h macro.h vtroutestyle.h layer.h obj_all_list.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_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h data.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + obj_subc_op.h operation.h obj_poly_op.h obj_pstk_inlines.h thermal.h \ + obj_pstk_draw.h obj_line_op.h obj_term.h obj_text_draw.h draw.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h compat_misc.h pcb_minuid.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/dom.h \ + ../src_3rd/liblihata/lihata.h ../src_3rd/liblihata/parser.h list_conf.h +obj_subc_list.o: obj_subc_list.c ../config.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + ../src_3rd/genht/ht.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.h data_parent.h rtree.h \ + obj_subc_list.h ht_subc.h ../src_3rd/genht/ht.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_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 const.h macro.h \ + global_typedefs.h pcb_bool.h unit.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h compat_misc.h obj_term.h \ + obj_subc_parent.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.h +obj_text.o: obj_text.c ../config.h rotate.h global_typedefs.h pcb_bool.h \ + unit.h board.h const.h macro.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + compat_misc.h compat_nls.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + event.h obj_text_op.h operation.h obj_poly_draw.h obj_arc_draw.h \ + obj_subc_parent.h draw.h obj_line_draw.h obj_text_draw.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 +obj_text_list.o: obj_text_list.c obj_poly_list.h obj_poly.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.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 \ + macro.h move.h misc_util.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 data.h layer.h attrib.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h hid.h error.h drc.h \ + layer_grp.h route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h board.h vtroutestyle.h \ + library.h rats_patch.h action_helper.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 rats.h netlist.h route_style.h \ + draw.h copy.h remove.h compat_misc.h compat_nls.h layer_vis.h \ + operation.h +operation.o: operation.c ../config.h operation.h global_typedefs.h \ + pcb_bool.h unit.h const.h board.h macro.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h rats.h netlist.h route_style.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 +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 compat_nls.h +pcb_bool.o: pcb_bool.c ../config.h pcb_bool.h compat_misc.h +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 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_3rd/genht/htsp.h ../src_3rd/genht/ht.h ../src_3rd/genht/hash.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/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_3rd/genlist/gentdlist_undef.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h globalconst.h error.h compat_misc.h \ + event.h +plug_footprint_act.o: plug_footprint_act.c ../config.h hid.h error.h \ + drc.h unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h plug_footprint.h vtlibrary.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 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 change.h board.h const.h \ + macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + plug_io.h remove.h paths.h hid_actions.h hid_flags.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_nls.h compat_lrealpath.h layer_vis.h \ + safe_fs.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 hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h remove.h search.h rats.h netlist.h route_style.h thermal.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h compat_nls.h obj_all.h \ + obj_poly_draw.h polygon_offs.c +polygon1.o: polygon1.c ../config.h rtree.h global_typedefs.h pcb_bool.h \ + unit.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 \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h data_parent.h macro.h box.h move.h misc_util.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + funchash_core.h funchash.h funchash_core_list.h draw.h search.h rats.h \ + netlist.h route_style.h compat_nls.h +rats.o: rats.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h find.h rats.h netlist.h route_style.h search.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h stub_mincut.h compat_misc.h \ + compat_nls.h obj_rat_draw.h obj_term.h obj_subc_parent.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h find.h \ + remove.h funchash_core.h funchash.h funchash_core_list.h compat_nls.h \ + rats.h netlist.h route_style.h draw.h obj_rat_draw.h +rats_patch.o: rats_patch.c rats_patch.h board.h ../config.h const.h \ + macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h ../src_3rd/genht/htsp.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h copy.h \ + compat_misc.h compat_nls.h safe_fs.h conf.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.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 +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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h draw.h hid.h error.h drc.h remove.h select.h operation.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h obj_all_op.h obj_arc_op.h \ + obj_elem_op.h obj_line_op.h obj_pad_op.h obj_pinvia_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 const.h ../config.h data.h globalconst.h \ + global_typedefs.h pcb_bool.h unit.h layer.h attrib.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.h tool.h ../src_3rd/genvector/vtp0.h remove.h board.h \ + vtroutestyle.h library.h rats_patch.h funchash_core.h funchash.h \ + funchash_core_list.h +rotate.o: rotate.c ../config.h board.h const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + rotate.h search.h rats.h netlist.h route_style.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/genvector/gds_char.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 compat_nls.h obj_all_op.h \ + obj_arc_op.h obj_elem_op.h obj_line_op.h obj_pad_op.h obj_pinvia_op.h \ + obj_poly_op.h obj_text_op.h obj_rat_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 math_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h \ + library.h rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 obj_arc_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 error.h conf.h global_typedefs.h pcb_bool.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 const.h macro.h \ + layer.h globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h obj_elem_list.h obj_elem.h obj_line_list.h \ + obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h obj_pinvia.h \ + obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h \ + funchash_core.h funchash.h funchash_core_list.h conf_core.h compat_nls.h +rtree.o: rtree.c ../config.h math_helper.h compat_cc.h rtree.h \ + global_typedefs.h pcb_bool.h unit.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + data_parent.h macro.h +safe_fs.o: safe_fs.c ../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 compat_inc.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + find.h search.h rats.h netlist.h route_style.h obj_subc_parent.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h search.h rats.h netlist.h route_style.h select.h operation.h \ + undo.h ../src_3rd/libuundo/uundo.h undo_old.h find.h compat_misc.h \ + compat_nls.h obj_elem_draw.h obj_pad_draw.h obj_arc_draw.h \ + obj_pinvia_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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.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 copy.h hid_attrib.h compat_misc.h \ + compat_nls.h +stub_draw.o: stub_draw.c ../config.h stub_draw.h hid.h error.h drc.h \ + unit.h global_typedefs.h pcb_bool.h attrib.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h obj_text_draw.h +stub_mincut.o: stub_mincut.c ../config.h stub_mincut.h global_typedefs.h \ + pcb_bool.h unit.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + data_parent.h +stub_stroke.o: stub_stroke.c error.h ../config.h pcb_bool.h +stub_vendor.o: stub_vendor.c ../config.h stub_vendor.h global_typedefs.h \ + pcb_bool.h unit.h +thermal.o: thermal.c ../config.h thermal.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h data_parent.h \ + layer.h obj_all_list.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_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h compat_misc.h data.h crosshair.h vtonpoint.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h hid.h error.h drc.h layer_grp.h \ + route.h const.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h rtree.h \ + ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + obj_pstk_inlines.h board.h vtroutestyle.h library.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 const.h macro.h vtroutestyle.h attrib.h layer.h \ + globalconst.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + data_parent.h obj_arc.h ../src_3rd/genlist/gentdlist_impl.h \ + ../src_3rd/genlist/gendlist.h ../src_3rd/genlist/gentdlist_undef.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h ../src_3rd/genht/ht.h obj_poly.h polyarea.h \ + obj_poly_list.h box.h math_helper.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h library.h rats_patch.h conf_core.h \ + conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 list_conf.h error.h event.h crosshair.h \ + vtonpoint.h hid.h drc.h route.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h data.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h search.h rats.h \ + netlist.h route_style.h tool.h undo.h ../src_3rd/libuundo/uundo.h \ + undo_old.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h buffer.h crosshair.h vtonpoint.h \ + hid.h error.h drc.h route.h data.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h hid_actions.h remove.h \ + search.h rats.h netlist.h route_style.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h buffer.h compat_misc.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h hid_actions.h \ + search.h rats.h netlist.h route_style.h tool.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h obj_elem_draw.h +tool_copy.o: tool_copy.c ../config.h action_helper.h global_typedefs.h \ + pcb_bool.h unit.h board.h const.h macro.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h copy.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h search.h rats.h netlist.h route_style.h tool.h \ + ../src_3rd/genvector/vtp0.h +tool_insert.o: tool_insert.c ../config.h action_helper.h \ + global_typedefs.h pcb_bool.h unit.h board.h const.h macro.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h compat_nls.h crosshair.h vtonpoint.h \ + hid.h error.h drc.h route.h insert.h polygon.h rtree.h search.h rats.h \ + netlist.h route_style.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h data.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h vtpadstack.h \ + obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h draw_wireframe.h find.h \ + rats.h netlist.h route_style.h search.h tool.h undo.h \ + ../src_3rd/libuundo/uundo.h undo_old.h obj_line_draw.h obj_pinvia_draw.h \ + obj_rat_draw.h +tool_lock.o: tool_lock.c ../config.h action_helper.h global_typedefs.h \ + pcb_bool.h unit.h board.h const.h macro.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h change.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h hid_actions.h search.h rats.h netlist.h route_style.h tool.h \ + ../src_3rd/genvector/vtp0.h tool_lock.h obj_elem_draw.h +tool_move.o: tool_move.c ../config.h action_helper.h global_typedefs.h \ + pcb_bool.h unit.h board.h const.h macro.h vtroutestyle.h attrib.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h compat_nls.h copy.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h search.h rats.h netlist.h \ + route_style.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 action_helper.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h route.h const.h hid_actions.h \ + polygon.h rtree.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 action_helper.h compat_nls.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h attrib.h layer.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h route.h const.h hid_actions.h \ + polygon.h rtree.h search.h rats.h netlist.h library.h route_style.h \ + vtroutestyle.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h crosshair.h vtonpoint.h hid.h error.h \ + drc.h route.h data.h buffer.h obj_subc_list.h obj_subc.h \ + ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.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 action_helper.h \ + global_typedefs.h pcb_bool.h unit.h board.h const.h macro.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h compat_nls.h event.h hid_actions.h \ + hid.h error.h drc.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h \ + remove.h search.h rats.h netlist.h route_style.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 action_helper.h \ + hid_actions.h hid.h error.h drc.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h rotate.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h compat_nls.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h ht_subc.h \ + vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h draw.h \ + hid_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 action_helper.h \ + global_typedefs.h pcb_bool.h unit.h board.h const.h macro.h \ + vtroutestyle.h attrib.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h layer.h globalconst.h \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h change.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + hid_actions.h search.h rats.h netlist.h route_style.h thermal.h tool.h \ + ../src_3rd/genvector/vtp0.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 action_helper.h board.h \ + const.h macro.h vtroutestyle.h attrib.h layer.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + obj_elem_list.h obj_elem.h obj_line_list.h obj_line.h obj_pad_list.h \ + obj_pad.h obj_pinvia_list.h obj_pinvia.h obj_text.h font.h \ + ../src_3rd/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h brave.h change.h compat_nls.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h \ + obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h rtree.h \ + ht_subc.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_pinvia_draw.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 const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h change.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h insert.h remove.h rotate.h search.h rats.h netlist.h \ + route_style.h undo.h ../src_3rd/libuundo/uundo.h undo_old.h flag_str.h \ + conf_core.h conf.h pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h compat_nls.h \ + obj_elem_draw.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 board.h const.h macro.h \ + vtroutestyle.h attrib.h layer.h obj_all_list.h obj_arc_list.h \ + obj_common.h ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h \ + flag.h data_parent.h obj_arc.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h obj_poly.h \ + polyarea.h obj_poly_list.h box.h math_helper.h move.h misc_util.h \ + ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h obj_pstk.h \ + obj_text_list.h obj_rat_list.h obj_rat.h layer_grp.h library.h \ + rats_patch.h data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h \ + buffer.h obj_subc_list.h obj_subc.h ../src_3rd/libminuid/libminuid.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + action_helper.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 rats.h \ + netlist.h route_style.h obj_line_draw.h tool.h +undo_old.o: undo_old.c ../config.h ../src_3rd/libuundo/uundo.h board.h \ + const.h macro.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 \ + obj_all_list.h obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h move.h misc_util.h ht_element.h ../src_3rd/genht/ht.h \ + obj_pstk_list.h obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h change.h data.h crosshair.h \ + vtonpoint.h hid.h error.h drc.h route.h buffer.h obj_subc_list.h \ + obj_subc.h ../src_3rd/libminuid/libminuid.h ../src_3rd/genht/htsp.h \ + rtree.h ht_subc.h vtpadstack.h obj_pstk_shape.h polygon.h vtpadstack_t.h \ + draw.h insert.h remove.h rotate.h search.h rats.h netlist.h \ + route_style.h undo.h undo_old.h flag_str.h conf_core.h conf.h \ + pcb-printf.h ../src_3rd/genvector/gds_char.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 compat_misc.h compat_nls.h \ + obj_elem_draw.h obj_poly_draw.h undo_old_str.h +unit.o: unit.c ../config.h compat_misc.h compat_nls.h unit.h +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 vtonpoint.h global_typedefs.h ../config.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 vtpadstack.h obj_pstk.h obj_common.h \ + ../src_3rd/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + data_parent.h layer.h obj_all_list.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_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h polyarea.h obj_poly_list.h box.h \ + math_helper.h macro.h move.h misc_util.h ht_element.h \ + ../src_3rd/genht/ht.h obj_pstk_list.h obj_text_list.h obj_rat_list.h \ + obj_rat.h obj_pstk_shape.h polygon.h rtree.h vtpadstack_t.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c +vtpadstack_t.o: vtpadstack_t.c vtpadstack_t.h obj_pstk_shape.h unit.h \ + ../config.h polygon.h flag.h globalconst.h rtree.h global_typedefs.h \ + pcb_bool.h math_helper.h polyarea.h layer.h attrib.h obj_all_list.h \ + obj_arc_list.h obj_common.h ../src_3rd/genht/hash.h \ + ../src_3rd/genlist/gendlist.h data_parent.h obj_arc.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h obj_elem_list.h obj_elem.h \ + obj_line_list.h obj_line.h obj_pad_list.h obj_pad.h obj_pinvia_list.h \ + obj_pinvia.h obj_text.h font.h ../src_3rd/genht/htip.h \ + ../src_3rd/genht/ht.h obj_poly.h obj_poly_list.h box.h macro.h move.h \ + misc_util.h ht_element.h ../src_3rd/genht/ht.h obj_pstk_list.h \ + obj_pstk.h obj_text_list.h obj_rat_list.h obj_rat.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 \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_3rd/genvector/genvector_impl.c Index: tags/1.2.7/src/Makefile.in =================================================================== --- tags/1.2.7/src/Makefile.in (nonexistent) +++ tags/1.2.7/src/Makefile.in (revision 13657) @@ -0,0 +1,456 @@ +# TODO default compiler flags +put /local/pcb/CFLAGS cc/cflags +append /local/pcb/CFLAGS cc/fpic +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 +put /local/pcb/DEPCFLAGS {} +put /tmpasm/OFS { } + +# 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 } + +include {../scconfig/template/debug.tmpasm} + +# main: objects +# 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 [@ + fptr_cast.o +@] + +put /local/pcb/OBJS [@ + action_helper.o + action_act.o + attrib.o + board.o + box.o + brave.o + buffer.o + build_run.o + change.o + change_act.o + conf.o + conf_act.o + conf_core.o + conf_hid.o + conf_internal.o + clip.o + compat_fs.o + compat_lrealpath.o + compat_misc.o + copy.o + crosshair.o + data.o + draw.o + error.o + event.o + font.o + font_act.o + file_act.o + find.o + find_act.o + flag.o + flag_str.o + funchash.o + gui_act.o + heap.o + hid_actions.o + hid_attrib.o + hid_cfg.o + hid_cfg_action.o + hid_cfg_input.o + hid_color.o + hid_draw_helpers.o + hid_extents.o + hid_flags.o + hid_helper.o + hid_init.o + hid_nogui.o + ht_element.o + ht_subc.o + insert.o + intersect.o + layer.o + layer_grp.o + layer_ui.o + layer_vis.o + library.o + list_conf.o + main.o + main_act.o + misc_util.o + move.o + netlist.o + netlist_act.o + object_act.o + obj_common.o + obj_any.o + obj_arc.o + obj_arc_list.o + obj_arc_ui.o + obj_elem.o + obj_elem_list.o + obj_line.o + obj_line_drcenf.o + obj_line_list.o + obj_pad.o + obj_pstk.o + obj_pstk_act.o + obj_pstk_list.o + obj_pstk_proto.o + obj_pad_list.o + obj_pinvia.o + obj_pinvia_therm.o + obj_pinvia_list.o + obj_poly.o + obj_poly_list.o + obj_rat.o + obj_rat_list.o + obj_subc.o + obj_subc_list.o + obj_term.o + obj_text.o + obj_text_list.o + operation.o + paths.o + pcb_bool.o + pcb_minuid.o + pcb-printf.o + plugins.o + plug_import.o + plug_io.o + plug_footprint.o + plug_footprint_act.o + polygon.o + polygon1.o + polygon_act.o + rats.o + rats_act.o + rats_patch.o + remove.o + remove_act.o + rotate.o + route.o + route_style.o + rtree.o + safe_fs.o + search.o + select.o + select_act.o + stub_draw.o + stub_mincut.o + stub_stroke.o + stub_vendor.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 + unit.o + vtlibrary.o + vtonpoint.o + vtpadstack.o + vtpadstack_t.o + vtroutestyle.o + buildin.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/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 + ../src_3rd/liblhtpers/lhtpers.o + ../src_3rd/genvector/gds_char.o + ../src_3rd/genvector/vtp0.o + ../src_3rd/genvector/vti0.o + ../src_3rd/genregex/regex_sei.o + ../src_3rd/genregex/regex_se.o + ../src_3rd/genregex/regex.o + ../src_3rd/qparse/qparse.o + ../src_3rd/libuundo/uundo.o + ../src_3rd/libuundo/uundo_debug.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 +put /local/pcb/OBJS_UTIL [@ + ../src_3rd/genvector/vts0.o +@] + +# main: action registrations +put /local/pcb/ACTION_REG_SRC { + action_act.c buffer.c brave.c change_act.c conf_act.c file_act.c find_act.c + gui_act.c main_act.c netlist_act.c font_act.c object_act.c + obj_pstk_act.c plugins.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} + +include {../src_plugins/plugins_ALL.tmpasm} + +append /local/pcb/CFLAGS /target/libs/sul/glib/cflags +append /local/pcb/CFLAGS /target/libs/sul/dmalloc/cflags +append /local/pcb/LIBS /target/libs/sul/glib/ldflags +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_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 +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_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@ + +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) + + +$(SPHASH_PATH)/sphash: $(SPHASH_PATH)/sphash.c + $(CC) -o pcb-rnd$(EXE) $(SPHASH_PATH)/sphash.c -o $(SPHASH_PATH)/sphash + +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 ##### + +pcblib_DATA= \ + default_font \ + default2.lht \ + default4.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) + +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 ../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-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/1.2.7/src/action_act.c =================================================================== --- tags/1.2.7/src/action_act.c (nonexistent) +++ tags/1.2.7/src/action_act.c (revision 13657) @@ -0,0 +1,112 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include +#include "config.h" + +#include "action_helper.h" +#include "hid_actions.h" +#include "undo.h" +#include "compat_nls.h" +#include "safe_fs.h" + +/* actions about actions + */ +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ExecuteFile[] = "ExecuteFile(filename)"; + +static const char pcb_acth_ExecuteFile[] = "Run actions from the given file."; + +/* %start-doc actions ExecuteFile + +Lines starting with @code{#} are ignored. + +%end-doc */ + +int pcb_act_ExecuteFile(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + FILE *fp; + const char *fname; + char line[256]; + int n = 0; + char *sp; + + if (argc != 1) + PCB_ACT_FAIL(ExecuteFile); + + fname = argv[0]; + + 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_hid_parse_actions(sp); + } + } + + defer_updates = 0; + if (defer_needs_update) { + pcb_undo_inc_serial(); + pcb_gui->invalidate_all(); + } + fclose(fp); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_hid_action_t action_action_list[] = { + {"ExecuteFile", 0, pcb_act_ExecuteFile, + pcb_acth_ExecuteFile, pcb_acts_ExecuteFile} +}; + +PCB_REGISTER_ACTIONS(action_action_list, NULL) Index: tags/1.2.7/src/action_helper.c =================================================================== --- tags/1.2.7/src/action_helper.c (nonexistent) +++ tags/1.2.7/src/action_helper.c (revision 13657) @@ -0,0 +1,254 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "board.h" +#include "change.h" +#include "copy.h" +#include "data.h" +#include "draw.h" +#include "find.h" +#include "insert.h" +#include "polygon.h" +#include "remove.h" +#include "rotate.h" +#include "search.h" +#include "select.h" +#include "undo.h" +#include "stub_stroke.h" +#include "funchash_core.h" +#include "hid_actions.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "event.h" + +#include "obj_pinvia_draw.h" +#include "obj_pad_draw.h" +#include "obj_line_draw.h" +#include "obj_arc_draw.h" +#include "obj_elem_draw.h" +#include "obj_text_draw.h" +#include "obj_rat_draw.h" +#include "obj_poly_draw.h" +#include "obj_pstk_draw.h" + +#include "tool.h" + + +/* --------------------------------------------------------------------------- */ + +/* %start-doc actions 00delta + +Many actions take a @code{delta} parameter as the last parameter, +which is an amount to change something. That @code{delta} may include +units, as an additional parameter, such as @code{Action(Object,5,mm)}. +If no units are specified, the default is PCB's native units +(currently 1/100 mil). Also, if the delta is prefixed by @code{+} or +@code{-}, the size is increased or decreased by that amount. +Otherwise, the size size is set to the given amount. + +@example +Action(Object,5,mil) +Action(Object,+0.5,mm) +Action(Object,-1) +@end example + +Actions which take a @code{delta} parameter which do not accept all +these options will specify what they do take. + +%end-doc */ + +/* %start-doc actions 00objects + +Many actions act on indicated objects on the board. They will have +parameters like @code{ToggleObject} or @code{SelectedVias} to indicate +what group of objects they act on. Unless otherwise specified, these +parameters are defined as follows: + +@table @code + +@item Object +@itemx ToggleObject +Affects the object under the mouse pointer. If this action is invoked +from a menu or script, the user will be prompted to click on an +object, which is then the object affected. + +@item Selected +@itemx SelectedObjects + +Affects all objects which are currently selected. At least, all +selected objects for which the given action makes sense. + +@item SelectedPins +@itemx SelectedVias +@itemx Selected@var{Type} +@itemx @i{etc} +Affects all objects which are both selected and of the @var{Type} specified. + +@end table + +%end-doc */ + +/* %start-doc actions 00macros + +@macro pinshapes + +Pins, pads, and vias can have various shapes. All may be round. Pins +and pads may be square (obviously "square" pads are usually +rectangular). Pins and vias may be octagonal. When you change a +shape flag of an element, you actually change all of its pins and +pads. + +Note that the square flag takes precedence over the octagon flag, +thus, if both the square and octagon flags are set, the object is +square. When the square flag is cleared, the pins and pads will be +either round or, if the octagon flag is set, octagonal. + +@end macro + +%end-doc */ + +int defer_updates = 0; +int defer_needs_update = 0; + + +void pcb_clear_warnings() +{ + pcb_rtree_it_t it; + pcb_box_t *n; + int li; + pcb_layer_t *l; + + conf_core.temp.rat_warn = pcb_false; + + for(n = pcb_r_first(PCB->Data->pin_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_pin_invalidate_draw((pcb_pin_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->via_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_via_invalidate_draw((pcb_pin_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->pad_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_pad_invalidate_draw((pcb_pad_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->padstack_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_pstk_invalidate_draw((pcb_pstk_t *)n); + } + } + pcb_r_end(&it); + + for(li = 0, l = PCB->Data->Layer; li < PCB->Data->LayerN; li++,l++) { + for(n = pcb_r_first(l->line_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_line_invalidate_draw(l, (pcb_line_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(l->arc_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_arc_invalidate_draw(l, (pcb_arc_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(l->polygon_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_poly_invalidate_draw(l, (pcb_poly_t *)n); + } + } + pcb_r_end(&it); + + for(n = pcb_r_first(l->text_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, (pcb_any_obj_t *)n)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, (pcb_any_obj_t *)n); + pcb_text_invalidate_draw(l, (pcb_text_t *)n); + } + } + pcb_r_end(&it); + } + + pcb_draw(); +} + +void pcb_release_mode(void) +{ + pcb_tool_release_mode(); + + if (pcb_tool_is_saved) + pcb_crosshair_restore_mode(); + pcb_tool_is_saved = pcb_false; +} + +void pcb_adjust_attached_objects(void) +{ + pcb_tool_adjust_attached_objects(); +} + +void pcb_notify_mode(void) +{ + if (conf_core.temp.rat_warn) + pcb_clear_warnings(); + pcb_tool_notify_mode(); +} + +void pcb_event_move_crosshair(int ev_x, int 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_notify_crosshair_change(pcb_true); /* xor-draw-remove from old loc */ + pcb_adjust_attached_objects(); + pcb_notify_crosshair_change(pcb_true); /* xor-draw-flush to new loc */ + } +} Index: tags/1.2.7/src/action_helper.h =================================================================== --- tags/1.2.7/src/action_helper.h (nonexistent) +++ tags/1.2.7/src/action_helper.h (revision 13657) @@ -0,0 +1,66 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_ACTION_HELPER_H +#define PCB_ACTION_HELPER_H + +#include "global_typedefs.h" + + +/* Event handler to set the cursor according to the X pointer position + called from inside main.c */ +void pcb_event_move_crosshair(int ev_x, int ev_y); + +/* adjusts the objects which are to be created like attached lines... */ +void pcb_adjust_attached_objects(void); + +#define PCB_ACTION_ARG(n) (argc > (n) ? argv[n] : NULL) + + +extern int defer_updates; +extern int defer_needs_update; + + + +/* 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); + +/* Clear warning color from pins/pads */ +void pcb_clear_warnings(void); + +void pcb_release_mode(void); + +/* --------------------------------------------------------------------------- + * Macros called by various action routines to show usage or to report + * a syntax error and fail + */ +#define PCB_AFAIL(x) { pcb_message(PCB_MSG_ERROR, "Syntax error. Usage:\n%s\n", (x##_syntax)); return 1; } + +#define PCB_ACT_FAIL(x) { pcb_message(PCB_MSG_ERROR, "Syntax error. Usage:\n%s\n", (pcb_acts_ ## x)); return 1; } + +#endif Index: tags/1.2.7/src/attrib.c =================================================================== --- tags/1.2.7/src/attrib.c (nonexistent) +++ tags/1.2.7/src/attrib.c (revision 13657) @@ -0,0 +1,176 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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(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/1.2.7/src/attrib.h =================================================================== --- tags/1.2.7/src/attrib.h (nonexistent) +++ tags/1.2.7/src/attrib.h (revision 13657) @@ -0,0 +1,80 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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(pcb_attribute_list_t * list, const char *name); +pcb_attribute_t *pcb_attribute_get_attr(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/1.2.7/src/board.c =================================================================== --- tags/1.2.7/src/board.c (nonexistent) +++ tags/1.2.7/src/board.c (revision 13657) @@ -0,0 +1,365 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#include "config.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "plug_io.h" +#include "compat_misc.h" +#include "hid_actions.h" +#include "paths.h" +#include "rtree.h" +#include "undo.h" +#include "draw.h" +#include "event.h" +#include "safe_fs.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); + free(pcb->Data); + + /* release font symbols */ + pcb_fontkit_free(&pcb->fontkit); + for (i = 0; i < PCB_NUM_NETLISTS; i++) + pcb_lib_free(&(pcb->NetlistLib[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, *save; + int i; + + /* allocate memory, switch all layers on and copy resources */ + ptr = calloc(1, sizeof(pcb_board_t)); + ptr->Data = pcb_buffer_new(ptr); + + ptr->ThermStyle = 4; + ptr->IsleArea = 2.e8; + 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 */ + /* this is the most useful starting point for now */ + + ptr->Grid = conf_core.editor.grid; + save = PCB; + PCB = ptr; + pcb_layer_parse_group_string(ptr, conf_core.design.groups, PCB_MAX_LAYER, 0); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + PCB = save; + + ptr->Zoom = conf_core.editor.zoom; + ptr->MaxWidth = conf_core.design.max_width; + ptr->MaxHeight = conf_core.design.max_height; + ptr->ID = pcb_create_ID_get(); + ptr->ThermScale = 0.5; + + ptr->Bloat = conf_core.design.bloat; + ptr->Shrink = conf_core.design.shrink; + ptr->minWid = conf_core.design.min_wid; + ptr->minSlk = conf_core.design.min_slk; + ptr->minDrill = conf_core.design.min_drill; + ptr->minRing = conf_core.design.min_ring; + + for (i = 0; i < PCB_MAX_LAYER; i++) + ptr->Data->Layer[i].name = pcb_strdup(conf_core.design.default_layer_name[i]); + + 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 = old; + return nw; +} + +int pcb_board_new_postproc(pcb_board_t *pcb, int use_defaults) +{ + /* copy default settings */ + pcb_layer_colors_from_conf(pcb); + return 0; +} + +void pcb_layer_colors_from_conf(pcb_board_t *ptr) +{ + int i; + + /* copy default settings */ + for (i = 0; i < PCB_MAX_LAYER; i++) { + ptr->Data->Layer[i].meta.real.color = conf_core.appearance.color.layer[i]; + ptr->Data->Layer[i].meta.real.selected_color = conf_core.appearance.color.layer_selected[i]; + } +} + +typedef struct { + int nplated; + int nunplated; +} HoleCountStruct; + +static pcb_r_dir_t hole_counting_old_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_t *) b; + HoleCountStruct *hcs = (HoleCountStruct *) cl; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) + hcs->nunplated++; + else + hcs->nplated++; + return PCB_R_DIR_FOUND_CONTINUE; +} + +#warning padstack TODO: 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; +} + +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->pin_tree, within_area, NULL, hole_counting_old_callback, &hcs, NULL); + pcb_r_search(pcb->Data->via_tree, within_area, NULL, hole_counting_old_callback, &hcs, NULL); + 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; +} + +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) +{ + if (Grid >= 1 && Grid <= PCB_MAX_GRID) { + if (align) { + PCB->GridOffsetX = pcb_crosshair.X % Grid; + PCB->GridOffsetY = pcb_crosshair.Y % Grid; + } + PCB->Grid = Grid; + conf_set_design("editor/grid", "%$mS", Grid); + if (conf_core.editor.draw_grid) + pcb_redraw(); + } +} + +/* 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->Changed = New; +} + + +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/1.2.7/src/board.h =================================================================== --- tags/1.2.7/src/board.h (nonexistent) +++ tags/1.2.7/src/board.h (revision 13657) @@ -0,0 +1,185 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 "const.h" +#include "macro.h" +#include +#include +#include +#include +#include +#include + +#include "global_typedefs.h" +#include "vtroutestyle.h" +#include "layer.h" +#include "layer_grp.h" +#include "library.h" +#include "attrib.h" +#include "rats_patch.h" +#include "font.h" + + /* 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; /* see macro.h */ + char *Name, /* name of board */ + *Filename, /* name of file (from load) */ + *PrintFilename, /* from print dialog */ + *Netlistname, /* name of netlist file */ + ThermStyle; /* type of thermal to place with thermal tool */ + pcb_bool Changed, /* layout has been changed */ + ViaOn, /* visibility flags */ + RatOn, InvisibleObjectsOn, PinOn, + RatDraw, /* we're drawing rats */ + SubcOn, SubcPartsOn, padstack_mark_on; + pcb_bool loose_subc; /* when set, subc parts are not locked into the subc */ + pcb_coord_t CursorX, /* cursor position as saved with layout */ + CursorY; + pcb_coord_t Bloat, /* drc sizes saved with layout */ + Shrink, minWid, minSlk, minDrill, minRing; + pcb_coord_t GridOffsetX, /* as saved with layout */ + GridOffsetY, MaxWidth, /* allowed size */ + MaxHeight; + + pcb_coord_t Grid; /* used grid with offsets */ + double Zoom, /* zoom factor */ + IsleArea, /* minimum poly island to retain */ + ThermScale; /* scale factor used with thermals */ + pcb_fontkit_t fontkit; + pcb_layer_stack_t LayerGroups; + vtroutestyle_t RouteStyle; + pcb_lib_t NetlistLib[PCB_NUM_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); + +/* Perhaps PCB should internally just use the Settings colors? For now, + * use this to set PCB colors so the config can reassign PCB colors. */ +void pcb_layer_colors_from_conf(pcb_board_t *); + +/* counts the number of plated and unplated holes 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); + +#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_TYPE_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 */ +void pcb_board_set_grid(pcb_coord_t Grid, pcb_bool align); + +/* 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); + + +/* Obsolete pcb_board_t field accessors - do not use */ +const char *pcb_board_get_filename(void); +const char *pcb_board_get_name(void); + +#endif Index: tags/1.2.7/src/box.c =================================================================== --- tags/1.2.7/src/box.c (nonexistent) +++ tags/1.2.7/src/box.c (revision 13657) @@ -0,0 +1,50 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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); +} Index: tags/1.2.7/src/box.h =================================================================== --- tags/1.2.7/src/box.h (nonexistent) +++ tags/1.2.7/src/box.h (revision 13657) @@ -0,0 +1,253 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "macro.h" +#include "move.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_BOX_MOVE_LOWLEVEL(b,dx,dy) \ + { \ + PCB_MOVE((b)->X1,(b)->Y1,(dx),(dy)) \ + PCB_MOVE((b)->X2,(b)->Y2,(dx),(dy)) \ + } + + +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, 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); + +#endif /* __BOX_H_INCLUDED__ */ Index: tags/1.2.7/src/brave.c =================================================================== --- tags/1.2.7/src/brave.c (nonexistent) +++ tags/1.2.7/src/brave.c (revision 13657) @@ -0,0 +1,279 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include + +#include "brave.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_PSTK_VIA, "pstk_via", "use padstack for vias", + "placing new vias will place padstacks instsad of old via objects", 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; + 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_DAD_DECL(dlg); + + PCB_DAD_BEGIN_VBOX(dlg); + 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); + } + 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_END(dlg); + + + PCB_DAD_NEW(dlg, "dlg_padstack_edit", "Edit padstack", 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 int pcb_act_Brave(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + desc_t *d; + if (argc == 0) + return brave_interact(); + + /* look up */ + if (argc > 0) { + d = find_by_name(argv[0]); + if (d == NULL) { + pcb_message(PCB_MSG_ERROR, "Unknown brave setting: %s\n", argv[0]); + return -1; + } + } + + if (argc > 1) + brave_set(d->bit, (pcb_strcasecmp(argv[1], "on") == 0)); + + pcb_message(PCB_MSG_INFO, "Brave setting: %s in %s\n", argv[0], (pcb_brave & d->bit) ? "on" : "off"); + + return 0; +} + +pcb_hid_action_t brave_action_list[] = { + {"Brave", 0, 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); + } +} Index: tags/1.2.7/src/brave.h =================================================================== --- tags/1.2.7/src/brave.h (nonexistent) +++ tags/1.2.7/src/brave.h (revision 13657) @@ -0,0 +1,13 @@ +#ifndef PCB_BRAVE_H +#define PCB_BRAVE_H +typedef enum { + PCB_BRAVE_OFF = 0, + PCB_BRAVE_PSTK_VIA = 1, + PCB_BRACE_max +} pcb_brave_t; + +extern pcb_brave_t pcb_brave; /* cache generated from the config */ + +void pcb_brave_init(void); + +#endif Index: tags/1.2.7/src/buffer.c =================================================================== --- tags/1.2.7/src/buffer.c (nonexistent) +++ tags/1.2.7/src/buffer.c (revision 13657) @@ -0,0 +1,939 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* functions used by paste- and move/copy buffer + */ +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "buffer.h" +#include "board.h" +#include "copy.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 "compat_nls.h" +#include "obj_all_op.h" +#include "obj_subc_op.h" +#include "obj_pstk_op.h" +#include "layer_grp.h" +#include "event.h" +#include "safe_fs.h" + +static pcb_opfunc_t AddBufferFunctions = { + pcb_lineop_add_to_buffer, + pcb_textop_add_to_buffer, + pcb_polyop_add_to_buffer, + pcb_viaop_add_to_buffer, + pcb_elemop_add_to_buffer, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_add_to_buffer, + pcb_ratop_add_to_buffer, + NULL, + pcb_subcop_add_to_buffer, + pcb_pstkop_add_to_buffer, +}; + +#warning TODO: rename this; move_to_buffer is also used to move from buffer to pcb +static pcb_opfunc_t MoveBufferFunctions = { + pcb_lineop_move_to_buffer, + pcb_textop_move_to_buffer, + pcb_polyop_move_to_buffer, + pcb_viaop_move_to_buffer, + pcb_elemop_move_to_buffer, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_move_to_buffer, + pcb_ratop_move_to_buffer, + NULL, + pcb_subcop_move_to_buffer, + pcb_pstkop_move_to_buffer, +}; + +int pcb_set_buffer_bbox(pcb_buffer_t *Buffer) +{ + pcb_box_t tmp, *box = pcb_data_bbox(&tmp, Buffer->Data, pcb_false); + + if (box) { + Buffer->BoundingBox = *box; + return 0; + } + return -1; +} + +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_free(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_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_TYPEMASK_ALL); + + /* 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); +} + +void pcb_buffer_move_selected(pcb_board_t *pcb, pcb_buffer_t *Buffer, pcb_coord_t X, pcb_coord_t Y, pcb_bool LeaveSelected) +{ + pcb_buffer_toss_selected(&MoveBufferFunctions, pcb, Buffer, X, Y, LeaveSelected); +} + +/*---------------------------------------------------------------------------*/ + +static const char pcb_acts_LoadFootprint[] = "pcb_load_footprint(filename[,refdes,value])"; + +static const char pcb_acth_LoadFootprint[] = "Loads a single footprint by name."; + +/* %start-doc actions LoadFootprint + +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. + +%end-doc */ + +int pcb_act_LoadFootprint(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *name = PCB_ACTION_ARG(0); + const char *refdes = PCB_ACTION_ARG(1); + const char *value = PCB_ACTION_ARG(2); + pcb_element_t *e; + pcb_subc_t *s; + pcb_cardinal_t len; + + if (!name) + PCB_ACT_FAIL(LoadFootprint); + + if (pcb_element_load_footprint_by_name(PCB_PASTEBUFFER, name)) + return 1; + + len = elementlist_length(&PCB_PASTEBUFFER->Data->Element) + pcb_subclist_length(&PCB_PASTEBUFFER->Data->subc); + + if (len == 0) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains no elements or subcircuits", name); + return 1; + } + if (len > 1) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains multiple elements and/or subcircuits", name); + return 1; + } + + e = elementlist_first(&PCB_PASTEBUFFER->Data->Element); + if (e != NULL) { + if (e->Name[0].TextString) + free(e->Name[0].TextString); + e->Name[0].TextString = pcb_strdup(name); + + if (e->Name[1].TextString) + free(e->Name[1].TextString); + e->Name[1].TextString = refdes ? pcb_strdup(refdes) : 0; + + if (e->Name[2].TextString) + free(e->Name[2].TextString); + e->Name[2].TextString = value ? pcb_strdup(value) : 0; + } + + s = pcb_subclist_first(&PCB_PASTEBUFFER->Data->subc); +#warning element TODO: remove this check when elements are removed: we know len == 1 + if (s != NULL) { + pcb_attribute_put(&s->Attributes, "refdes", refdes); + pcb_attribute_put(&s->Attributes, "name", name); + pcb_attribute_put(&s->Attributes, "value", value); + } + + 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 = newPCB->CursorX; + Buffer->Y = newPCB->CursorY; + 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_rotate(pcb_buffer_t *Buffer, pcb_uint8_t Number) +{ + /* rotate vias */ + PCB_VIA_LOOP(Buffer->Data); + { + pcb_r_delete_entry(Buffer->Data->via_tree, (pcb_box_t *) via); + PCB_VIA_ROTATE90(via, Buffer->X, Buffer->Y, Number); + pcb_pin_bbox(via); + pcb_r_insert_entry(Buffer->Data->via_tree, (pcb_box_t *) via, 0); + } + PCB_END_LOOP; + + /* elements */ + PCB_ELEMENT_LOOP(Buffer->Data); + { + pcb_element_rotate90(Buffer->Data, element, Buffer->X, Buffer->Y, Number); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(Buffer->Data); + { + pcb_obj_rotate90(PCB_TYPE_SUBC, subc, subc, subc, Buffer->X, Buffer->Y, Number); + } + PCB_END_LOOP; + + /* all layer related objects */ + PCB_LINE_ALL_LOOP(Buffer->Data); + { + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + pcb_line_rotate90(line, Buffer->X, Buffer->Y, Number); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line, 0); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Buffer->Data); + { + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + pcb_arc_rotate90(arc, Buffer->X, Buffer->Y, Number); + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc, 0); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Buffer->Data); + { + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + pcb_text_rotate90(text, Buffer->X, Buffer->Y, Number); + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *) text, 0); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Buffer->Data); + { + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *) polygon); + pcb_poly_rotate90(polygon, Buffer->X, Buffer->Y, Number); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon, 0); + } + 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); +} + +void pcb_buffer_free_rotate(pcb_buffer_t *Buffer, pcb_angle_t angle) +{ + double cosa, sina; + + cosa = cos(angle * M_PI / 180.0); + sina = sin(angle * M_PI / 180.0); + + /* rotate vias */ + PCB_VIA_LOOP(Buffer->Data); + { + pcb_via_rotate(Buffer->Data, via, Buffer->X, Buffer->Y, cosa, sina); + } + PCB_END_LOOP; + + /* elements */ + PCB_ELEMENT_LOOP(Buffer->Data); + { + pcb_element_rotate(Buffer->Data, element, 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; + /* FIXME: rotate text */ + 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_data_t *pcb_buffer_new(pcb_board_t *pcb) +{ + return pcb_data_new(pcb); +} + + +/* -------------------------------------------------------------------------- */ + +static const char pcb_acts_FreeRotateBuffer[] = "pcb_buffer_free_rotate([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"; + +/* %start-doc actions FreeRotateBuffer + +Rotates the contents of the pastebuffer by an arbitrary angle. If no +angle is given, the user is prompted for one. + +%end-doc */ + +int pcb_act_FreeRotateBuffer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *angle_s; + + if (argc < 1) + angle_s = pcb_gui->prompt_for("Enter Rotation (degrees, CCW):", "0"); + else + angle_s = argv[0]; + + if (angle_s == NULL) + return 0; + + pcb_notify_crosshair_change(pcb_false); + pcb_buffer_free_rotate(PCB_PASTEBUFFER, strtod(angle_s, 0)); + 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); + free(pcb_buffers[i].Data); + } +} + +void pcb_buffer_mirror(pcb_board_t *pcb, pcb_buffer_t *Buffer) +{ + int i, num_layers; + + if (elementlist_length(&Buffer->Data->Element)) { + pcb_message(PCB_MSG_ERROR, _("You can't mirror a buffer that has elements!\n")); + return; + } + + 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_data_mirror(Buffer->Data, 0, pcb_false, pcb_false); + 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; + + PCB_ELEMENT_LOOP(Buffer->Data); + { + r_delete_element(Buffer->Data, element); + pcb_element_mirror(Buffer->Data, element, 0); + } + PCB_END_LOOP; + +#warning subc TODO + + /* set buffer offset to 'mark' position */ + Buffer->X = PCB_SWAP_X(Buffer->X); + Buffer->Y = PCB_SWAP_Y(Buffer->Y); + PCB_VIA_LOOP(Buffer->Data); + { + pcb_via_flip_side(Buffer->Data, via); + } + 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); +#warning layer TODO: 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++) { + int t1, t2; + 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++; + /* move the thermal flags with the layers */ + PCB_PIN_ALL_LOOP(Buffer->Data); + { + t1 = PCB_FLAG_THERM_TEST(snumber, pin); + t2 = PCB_FLAG_THERM_TEST(cnumber, pin); + PCB_FLAG_THERM_ASSIGN(snumber, t2, pin); + PCB_FLAG_THERM_ASSIGN(cnumber, t1, pin); + } + PCB_ENDALL_LOOP; + PCB_VIA_LOOP(Buffer->Data); + { + t1 = PCB_FLAG_THERM_TEST(snumber, via); + t2 = PCB_FLAG_THERM_TEST(cnumber, via); + PCB_FLAG_THERM_ASSIGN(snumber, t2, via); + PCB_FLAG_THERM_ASSIGN(cnumber, t1, via); + } + PCB_END_LOOP; + } + } + 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 + + /* 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); + + 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 elements */ + if (pcb->PinOn && pcb_silk_on(pcb)) { + PCB_ELEMENT_LOOP(PCB_PASTEBUFFER->Data); + { +#ifdef DEBUG + printf("In CopyPastebufferToLayout, pasting element %s\n", element->Name[1].TextString); +#endif + if (PCB_FRONT(element) || pcb->InvisibleObjectsOn) { + pcb_elemop_copy(&ctx, element); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + /* paste subcircuits */ + PCB_SUBC_LOOP(PCB_PASTEBUFFER->Data); + { + pcb_subcop_copy(&ctx, subc); + changed = pcb_true; + } + PCB_END_LOOP; + + /* finally the vias and padstacks */ + if (pcb->ViaOn) { + changed |= (pinlist_length(&(PCB_PASTEBUFFER->Data->Via)) != 0); + PCB_VIA_LOOP(PCB_PASTEBUFFER->Data); + { + pcb_viaop_copy(&ctx, via); + } + PCB_END_LOOP; + } + + if (pcb->ViaOn) { + 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 */ +#warning subc TODO: 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_draw(); + pcb_undo_inc_serial(); + } + +#ifdef DEBUG + printf(" .... Leaving CopyPastebufferToLayout.\n"); +#endif + + 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(); + } +} + + +/* ---------------------------------------------------------------------- */ + +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(Save, Filename, [format], [force])"; + +static const char pcb_acth_PasteBuffer[] = "Various operations on the paste buffer."; + +/* %start-doc actions PasteBuffer + +There are a number of paste buffers; the actual limit is a +compile-time constant @code{PCB_MAX_BUFFER} in @file{globalconst.h}. It +is currently @code{5}. One of these is the ``current'' paste buffer, +often referred to as ``the'' paste buffer. + +@table @code + +@item AddSelected +Copies the selected objects to the current paste buffer. + +@item Clear +Remove all objects from the current paste buffer. + +@item Convert +Convert the current paste buffer to an element. Vias are converted to +pins, lines are converted to pads. + +@item Restore +Convert any elements in the paste buffer back to vias and lines. + +@item Mirror +Flip all objects in the paste buffer vertically (up/down flip). To mirror +horizontally, combine this with rotations. + +@item 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). + +@item 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. + +@item ToLayout +Pastes any elements in the current buffer to the indicated X, Y +coordinates in the layout. The @code{X} and @code{Y} are treated like +@code{delta} is for many other objects. For each, if it's prefixed by +@code{+} or @code{-}, then that amount is relative to the last +location. Otherwise, it's absolute. Units can be +@code{mil} or @code{mm}; if unspecified, units are PCB's internal +units, currently 1/100 mil. + + +@item 1..PCB_MAX_BUFFER +Selects the given buffer to be the current paste buffer. + +@end table + +%end-doc */ +static int pcb_act_PasteBuffer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = argc ? argv[0] : ""; + const char *sbufnum = argc > 1 ? argv[1] : ""; + const char *fmt = argc > 2 ? argv[2] : NULL; + const char *forces = argc > 3 ? argv[3] : NULL; + const char *name; + static char *default_file = NULL; + pcb_bool free_name = pcb_false; + int force = (forces != NULL) && ((*forces == '1') || (*forces == 'y') || (*forces == 'Y')); + + pcb_notify_crosshair_change(pcb_false); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + /* clear contents of paste buffer */ + case F_Clear: + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + break; + + /* copies objects to paste buffer */ + case F_AddSelected: + pcb_buffer_add_selected(PCB, PCB_PASTEBUFFER, 0, 0, pcb_false); + break; + + /* moves objects to paste buffer */ + case F_MoveSelected: + pcb_buffer_move_selected(PCB, PCB_PASTEBUFFER, 0, 0, pcb_false); + break; + + /* converts buffer contents into an element */ + case F_Convert: + pcb_element_convert_from_buffer(PCB_PASTEBUFFER); + break; + + /* converts buffer contents into an element */ + case F_ConvertSubc: + pcb_subc_convert_from_buffer(PCB_PASTEBUFFER); + break; + + /* break up element for editing */ + case F_Restore: + if (!pcb_element_smash_buffer(PCB_PASTEBUFFER) && !pcb_subc_smash_buffer(PCB_PASTEBUFFER)) + pcb_message(PCB_MSG_ERROR, _("Error! Buffer doesn't contain a single element or subcircuit\n")); + break; + + /* Mirror buffer */ + case F_Mirror: + pcb_buffer_mirror(PCB, PCB_PASTEBUFFER); + break; + + case F_Rotate: + if (sbufnum) { + pcb_buffer_rotate(PCB_PASTEBUFFER, (pcb_uint8_t) atoi(sbufnum)); + 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", "footprint", 0); + + if (default_file) { + free(default_file); + default_file = NULL; + } + if (name && *name) { + default_file = pcb_strdup(name); + } + free_name = pcb_true; + } + + else + name = argv[1]; + + { + FILE *exist; + + if ((!force) && ((exist = pcb_fopen(name, "r")))) { + fclose(exist); + if (pcb_gui->confirm_dialog(_("File exists! Ok to overwrite?"), 0)) + 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 == 1) { + x = y = 0; + } + else if (argc == 3 || argc == 4) { + x = pcb_get_value(PCB_ACTION_ARG(1), PCB_ACTION_ARG(3), &absolute, NULL); + if (!absolute) + x += oldx; + y = pcb_get_value(PCB_ACTION_ARG(2), PCB_ACTION_ARG(3), &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; + + /* set number */ + default: + { + int number = atoi(function); + + /* correct number */ + if (number) + pcb_buffer_set_number(number - 1); + } + } + } + + pcb_notify_crosshair_change(pcb_true); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_hid_action_t buffer_action_list[] = { + {"FreeRotateBuffer", 0, pcb_act_FreeRotateBuffer, + pcb_acth_FreeRotateBuffer, pcb_acts_FreeRotateBuffer} + , + {"LoadFootprint", 0, pcb_act_LoadFootprint, + pcb_acth_LoadFootprint, pcb_acts_LoadFootprint} + , + {"PasteBuffer", 0, pcb_act_PasteBuffer, + pcb_acth_PasteBuffer, pcb_acts_PasteBuffer} +}; + +PCB_REGISTER_ACTIONS(buffer_action_list, NULL) Index: tags/1.2.7/src/buffer.h =================================================================== --- tags/1.2.7/src/buffer.h (nonexistent) +++ tags/1.2.7/src/buffer.h (revision 13657) @@ -0,0 +1,101 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Board independent paste buffers */ + +#ifndef PCB_BUFFER_H +#define PCB_BUFFER_H + +#include "obj_common.h" + +struct pcb_buffer_s { /* information about the paste buffer */ + pcb_coord_t X, Y; /* offset */ + pcb_box_t BoundingBox; + 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); + +/* moves all selected and visible objects to the paste buffer */ +void pcb_buffer_move_selected(pcb_board_t *pcb, pcb_buffer_t *Buffer, pcb_coord_t X, pcb_coord_t Y, pcb_bool LeaveSelected); + +/* 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_rotate(pcb_buffer_t *Buffer, pcb_uint8_t Number); +void pcb_buffer_free_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); + +/* 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() */ +int pcb_act_LoadFootprint(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); + +/* 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); + + +/* 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/1.2.7/src/build_run.c =================================================================== --- tags/1.2.7/src/build_run.c (nonexistent) +++ tags/1.2.7/src/build_run.c (revision 13657) @@ -0,0 +1,290 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996,2006 Thomas Nau + * pcb-rnd Copyright (C) 2017 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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); +/** pcb_quit_app: + * Quits application + */ +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); +} + +/** pcb_get_info_program: + * Returns a string that has a bunch of information about this program. + */ +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; +} + +/** pcb_get_info_copyright: + * Returns a string that has a bunch of information about the copyrights. + */ +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..2017 (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; +} + +/** pcb_get_info_websites: + * Returns a string that has a bunch of information about the websites. + */ +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; +} + +/** pcb_get_info_comments: + * Returns a string as the concatenation of pcb_get_info_program() and pcb_get_info_websites() + */ +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; +} + + +/** pcb_get_info_compile_options: + * Returns a string that has a bunch of information about the options selected at compile time. + */ +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; +} + +/** pcb_get_infostr: + * Returns a string that has a bunch of information about this copy of pcb. + * Can be used for things like "about" dialog boxes. + */ +char *pcb_get_infostr(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_copyright(); + gds_append_str(&info, tmp); + gds_append_str(&info, "\n\n"); + 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 LICENSE file for more information\n\n"); + tmp = pcb_get_info_websites(NULL); + gds_append_str(&info, tmp); + + tmp = pcb_get_info_compile_options(); + gds_append_str(&info, tmp); + } + 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(); +} + +/** pcb_catch_signal: + * 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/1.2.7/src/build_run.h =================================================================== --- tags/1.2.7/src/build_run.h (nonexistent) +++ tags/1.2.7/src/build_run.h (revision 13657) @@ -0,0 +1,41 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +void pcb_quit_app(void); + +char *pcb_get_info_program(void); +char *pcb_get_info_copyright(void); +char *pcb_get_info_websites(const char **url_out); +char *pcb_get_info_comments(void); +char *pcb_get_info_compile_options(void); + +char *pcb_get_infostr(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); Index: tags/1.2.7/src/buildin.h =================================================================== --- tags/1.2.7/src/buildin.h (nonexistent) +++ tags/1.2.7/src/buildin.h (revision 13657) @@ -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/1.2.7/src/change.c =================================================================== --- tags/1.2.7/src/change.c (nonexistent) +++ tags/1.2.7/src/change.c (revision 13657) @@ -0,0 +1,1363 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* functions used to change object properties + * + */ + +#include "config.h" + +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "select.h" +#include "undo.h" +#include "hid_actions.h" +#include "compat_nls.h" +#include "obj_all_op.h" +#include "obj_pstk_op.h" +#include "obj_subc_parent.h" +#include "obj_term.h" + +pcb_opfunc_t ChangeSizeFunctions = { + pcb_lineop_change_size, + pcb_textop_change_size, + pcb_polyop_change_clear, + pcb_viaop_change_size, + pcb_elemop_change_size, /* changes silk screen line width */ + pcb_elemop_change_name_size, + pcb_pinop_change_size, + pcb_padop_change_size, + 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, + pcb_viaop_change_size, + pcb_elemop_change_1st_size, + pcb_elemop_change_name_size, + pcb_pinop_change_size, + pcb_padop_change_size, + NULL, + NULL, + pcb_arcop_change_size, + NULL, + NULL, + pcb_subcop_change_1st_size, + NULL /* padstack */ +}; + +pcb_opfunc_t Change2ndSizeFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_change_2nd_size, + pcb_elemop_change_2nd_size, + NULL, + pcb_pinop_change_2nd_size, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_2nd_size, + pcb_pstkop_change_2nd_size +}; + +static pcb_opfunc_t ChangeThermalFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_change_thermal, + NULL, + NULL, + pcb_pinop_change_thermal, + 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 :-) */ + pcb_viaop_change_clear_size, + pcb_elemop_change_clear_size, + NULL, + pcb_pinop_change_clear_size, + pcb_padop_change_clear_size, + NULL, + NULL, + pcb_arcop_change_clear_size, + NULL, + NULL, + pcb_subcop_change_clear_size, + pcb_pstkop_change_clear_size +}; + +static pcb_opfunc_t ChangeNameFunctions = { + pcb_lineop_change_name, + pcb_textop_change_name, + NULL, + pcb_viaop_change_name, + pcb_elemop_change_name, + NULL, + pcb_pinop_change_name, + pcb_padop_change_name, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_name, + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangePinnumFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_pinop_change_num, + pcb_padop_change_num, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL /* padstack */ +}; + +pcb_opfunc_t ChangeSquareFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_change_square, + pcb_elemop_change_square, + NULL, + pcb_pinop_change_square, + pcb_padop_change_square, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_square, + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeNonetlistFunctions = { + NULL, + NULL, + NULL, + NULL, + pcb_elemop_change_nonetlist, + 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, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_change_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +pcb_opfunc_t ChangeOctagonFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_change_octagon, + pcb_elemop_change_octagon, + NULL, + pcb_pinop_change_octagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_change_octagon, + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeMaskSizeFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_change_mask_size, +#if 0 + ChangeElementMaskSize, +#else + NULL, +#endif + NULL, + pcb_pinop_change_mask_size, + pcb_padop_change_mask_size, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +pcb_opfunc_t SetSquareFunctions = { + NULL, + NULL, + NULL, + NULL, + pcb_elemop_set_square, + NULL, + pcb_pinop_set_square, + pcb_padop_set_square, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_set_square, + NULL /* padstack */ +}; + +static pcb_opfunc_t SetJoinFunctions = { + pcb_lineop_set_join, + pcb_textop_set_join, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_set_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +pcb_opfunc_t SetOctagonFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_set_octagon, + pcb_elemop_set_octagon, + NULL, + pcb_pinop_set_octagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_set_octagon, + NULL /* padstack */ +}; + +pcb_opfunc_t ClrSquareFunctions = { + NULL, + NULL, + NULL, + NULL, + pcb_elemop_clear_square, + NULL, + pcb_pinop_clear_square, + pcb_padop_clear_square, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_clear_square, + NULL /* padstack */ +}; + +static pcb_opfunc_t ClrJoinFunctions = { + pcb_lineop_clear_join, + pcb_textop_clear_join, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_clear_join, + NULL, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +pcb_opfunc_t ClrOctagonFunctions = { + NULL, + NULL, + NULL, + pcb_viaop_clear_octagon, + pcb_elemop_clear_octagon, + NULL, + pcb_pinop_clear_octagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_subcop_clear_octagon, /* subc */ + NULL /* padstack */ +}; + +static pcb_opfunc_t ChangeRadiusFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + 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, + 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, + pcb_viaop_change_flag, + NULL, + NULL, + pcb_pinop_change_flag, + pcb_padop_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, + pcb_pinop_invalidate_label, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_invalidate_label, + NULL, + NULL, + /*pcb_subcop_invalidate_flag*/ NULL, + NULL /* padstack */ +}; + + +/* ---------------------------------------------------------------------- + * changes the thermals on all selected and visible pins + * and/or vias. 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); + 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); + 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; + + if (pcb_mask_on(PCB)) + change = pcb_selected_operation(PCB, PCB->Data, &ChangeMaskSizeFunctions, &ctx, pcb_false, types); + else + change = pcb_selected_operation(PCB, PCB->Data, &ChangeClearSizeFunctions, &ctx, pcb_false, types); + 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); + 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); + 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); + 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); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * changes the nonetlist-flag of all selected and visible elements + * 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); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +#if 0 +/* ---------------------------------------------------------------------- + * sets the square-flag of all selected and visible pins or pads + * returns pcb_true if anything has changed + */ +pcb_bool SetSelectedNonetlist(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &SetNonetlistFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * clears the square-flag of all selected and visible pins or pads + * returns pcb_true if anything has changed + */ +pcb_bool ClrSelectedNonetlist(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ClrNonetlistFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} +#endif + +/* ---------------------------------------------------------------------- + * changes the square-flag of all selected and visible pins or pads + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_square(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeSquareFunctions, &ctx, pcb_false, types); + 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); + 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); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + + +/* ---------------------------------------------------------------------- + * sets the square-flag of all selected and visible pins or pads + * returns pcb_true if anything has changed + */ +pcb_bool pcb_set_selected_square(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &SetSquareFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * clears the square-flag of all selected and visible pins or pads + * returns pcb_true if anything has changed + */ +pcb_bool pcb_clr_selected_square(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ClrSquareFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * changes the octagon-flag of all selected and visible pins and vias + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_octagon(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ChangeOctagonFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * sets the octagon-flag of all selected and visible pins and vias + * returns pcb_true if anything has changed + */ +pcb_bool pcb_set_selected_octagon(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &SetOctagonFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * clears the octagon-flag of all selected and visible pins and vias + * returns pcb_true if anything has changed + */ +pcb_bool pcb_clr_selected_octagon(int types) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + change = pcb_selected_operation(PCB, PCB->Data, &ClrOctagonFunctions, &ctx, pcb_false, types); + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * changes the hole-flag of all selected and visible vias + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_hole(void) +{ + pcb_bool change = pcb_false; + + if (PCB->ViaOn) + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, via)) + change |= pcb_pin_change_hole(via); + } + PCB_END_LOOP; + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + +/* ---------------------------------------------------------------------- + * changes the no paste-flag of all selected and visible pads + * returns pcb_true if anything has changed + */ +pcb_bool pcb_chg_selected_paste(void) +{ + pcb_bool change = pcb_false; + + PCB_PAD_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad)) + change |= pcb_pad_change_paste(pad); + } + PCB_ENDALL_LOOP; + if (change) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (change); +} + + +/* --------------------------------------------------------------------------- + * changes the size of the passed object; element size is silk size + * 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); +} + +/* --------------------------------------------------------------------------- + * 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; + + if (pcb_mask_on(PCB)) + change = (pcb_object_operation(&ChangeMaskSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + else + 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 mask size of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_mask_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(&ChangeMaskSizeFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL); + if (change) { + pcb_draw(); + 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 pin number 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_pinnum(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(&ChangePinnumFunctions, &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); +} + +/* --------------------------------------------------------------------------- + * changes the square-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_square(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int style) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + ctx.chgsize.value = style; + + if (pcb_object_operation(&ChangeSquareFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * sets the square-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_set_obj_square(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&SetSquareFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * clears the square-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_clr_obj_square(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ClrSquareFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * changes the octagon-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_chg_obj_octagon(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ChangeOctagonFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * sets the octagon-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_set_obj_octagon(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&SetOctagonFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * clears the octagon-flag of the passed object + * Returns pcb_true if anything is changed + */ +pcb_bool pcb_clr_obj_octagon(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.chgsize.pcb = PCB; + + if (pcb_object_operation(&ClrOctagonFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3) != NULL) { + pcb_draw(); + pcb_undo_inc_serial(); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * queries the user for a new object name and changes it + * + * The allocated memory isn't freed because the old string is used + * by the undo module. + */ +void *pcb_chg_obj_name_query(int Type, void *Ptr1, void *Ptr2, void *Ptr3, int pinnum) +{ + char *name = NULL; + char msg[513]; + pcb_any_obj_t *obj = Ptr2; + pcb_subc_t *parent_subc; + + /* if passed an element name, make it an element reference instead */ + if (Type == PCB_TYPE_ELEMENT_NAME) { + Type = PCB_TYPE_ELEMENT; + Ptr2 = Ptr1; + Ptr3 = Ptr1; + } + + parent_subc = pcb_obj_parent_subc(obj); + if (parent_subc != NULL) { + name = pcb_gui->prompt_for(_("Enter terminal ID:"), PCB_EMPTY(obj->term)); + if (name != NULL) { + pcb_term_undoable_rename(PCB, obj, name); + pcb_draw(); + } + return Ptr3; + } + + switch (Type) { + case PCB_TYPE_LINE: + name = pcb_gui->prompt_for(_("Linename:"), PCB_EMPTY(((pcb_line_t *) Ptr2)->Number)); + break; + + case PCB_TYPE_VIA: + name = pcb_gui->prompt_for(_("Vianame:"), PCB_EMPTY(((pcb_pin_t *) Ptr2)->Name)); + break; + + case PCB_TYPE_PIN: + if (pinnum) + sprintf(msg, _("%s Pin Number:"), PCB_EMPTY(((pcb_pin_t *) Ptr2)->Number)); + else + sprintf(msg, _("%s Pin Name:"), PCB_EMPTY(((pcb_pin_t *) Ptr2)->Number)); + name = pcb_gui->prompt_for(msg, PCB_EMPTY(((pcb_pin_t *) Ptr2)->Name)); + break; + + case PCB_TYPE_PAD: + if (pinnum) + sprintf(msg, _("%s Pad Number:"), PCB_EMPTY(((pcb_pad_t *) Ptr2)->Number)); + else + sprintf(msg, _("%s Pad Name:"), PCB_EMPTY(((pcb_pad_t *) Ptr2)->Number)); + name = pcb_gui->prompt_for(msg, PCB_EMPTY(((pcb_pad_t *) Ptr2)->Name)); + break; + + case PCB_TYPE_TEXT: + name = pcb_gui->prompt_for(_("Enter text:"), PCB_EMPTY(((pcb_text_t *) Ptr2)->TextString)); + break; + + case PCB_TYPE_ELEMENT: + name = pcb_gui->prompt_for(_("Elementname:"), PCB_EMPTY(PCB_ELEM_NAME_VISIBLE(PCB, (pcb_element_t *) Ptr2))); + break; + + case PCB_TYPE_SUBC: + name = pcb_gui->prompt_for(_("Subcircuit refdes:"), PCB_EMPTY(((pcb_subc_t *)Ptr2)->refdes)); + break; + } + if (name) { + /* NB: ChangeObjectName takes ownership of the passed memory */ + char *old; + if (pinnum) + old = (char *) pcb_chg_obj_pinnum(Type, Ptr1, Ptr2, Ptr3, name); + else + old = (char *) pcb_chg_obj_name(Type, Ptr1, Ptr2, Ptr3, name); + + if (old != (char *) -1) { + if (pinnum) + pcb_undo_add_obj_to_change_pinnum(Type, Ptr1, Ptr2, Ptr3, old); + else + pcb_undo_add_obj_to_change_name(Type, Ptr1, Ptr2, Ptr3, old); + pcb_undo_inc_serial(); + } + pcb_draw(); + return (Ptr3); + } + 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(int 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/1.2.7/src/change.h =================================================================== --- tags/1.2.7/src/change.h (nonexistent) +++ tags/1.2.7/src/change.h (revision 13657) @@ -0,0 +1,117 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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" + +#define PCB_CHANGENAME_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PSTK | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_SUBC_PART | PCB_TYPE_SUBC) + +#define PCB_CHANGESIZE_TYPES \ + (PCB_TYPE_PSTK | PCB_TYPE_POLY | PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_LINE | \ + PCB_TYPE_ARC | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_SUBC_PART ) + +#define PCB_CHANGE2NDSIZE_TYPES \ + (PCB_TYPE_PSTK | PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC| PCB_TYPE_SUBC_PART) + +/* We include polygons here only to inform the user not to do it that way. */ +#define PCB_CHANGECLEARSIZE_TYPES \ + (PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_SUBC| PCB_TYPE_SUBC_PART) + +#define PCB_CHANGENONETLIST_TYPES \ + (PCB_TYPE_ELEMENT | PCB_TYPE_SUBC) + +#define PCB_CHANGESQUARE_TYPES \ + (PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_VIA | PCB_TYPE_SUBC_PART) + +#define PCB_CHANGEOCTAGON_TYPES \ + (PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_PIN | PCB_TYPE_VIA | PCB_TYPE_SUBC_PART) + +#define PCB_CHANGEJOIN_TYPES \ + (PCB_TYPE_ARC | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_POLY) + +#define PCB_CHANGETHERMAL_TYPES \ + (PCB_TYPE_PIN | PCB_TYPE_VIA | PCB_TYPE_SUBC_PART) + +#define PCB_CHANGEMASKSIZE_TYPES \ + (PCB_TYPE_PIN | PCB_TYPE_VIA | PCB_TYPE_PAD | PCB_TYPE_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_mask_size(int, pcb_coord_t, 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_square(int); +pcb_bool pcb_set_selected_square(int); +pcb_bool pcb_clr_selected_square(int); +pcb_bool pcb_chg_selected_thermals(int types, int therm_style, unsigned long lid); +pcb_bool pcb_chg_selected_hole(void); +pcb_bool pcb_chg_selected_paste(void); +pcb_bool pcb_chg_selected_octagon(int); +pcb_bool pcb_set_selected_octagon(int); +pcb_bool pcb_clr_selected_octagon(int); +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_mask_size(int, void *, void *, void *, pcb_coord_t, 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); +pcb_bool pcb_chg_obj_square(int, void *, void *, void *, int); +pcb_bool pcb_set_obj_square(int, void *, void *, void *); +pcb_bool pcb_clr_obj_square(int, void *, void *, void *); +pcb_bool pcb_chg_obj_octagon(int, void *, void *, void *); +pcb_bool pcb_set_obj_octagon(int, void *, void *, void *); +pcb_bool pcb_clr_obj_octagon(int, void *, void *, void *); +void *pcb_chg_obj_name(int, void *, void *, void *, char *); +void *pcb_chg_obj_name_query(int, void *, void *, void *, int); +void *pcb_chg_obj_pinnum(int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *Name); +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(int Type, void *Ptr1, void *Ptr2, void *Ptr3); + +#endif Index: tags/1.2.7/src/change_act.c =================================================================== --- tags/1.2.7/src/change_act.c (nonexistent) +++ tags/1.2.7/src/change_act.c (revision 13657) @@ -0,0 +1,1581 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "hid_actions.h" +#include "change.h" +#include "draw.h" +#include "search.h" +#include "undo.h" +#include "event.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "obj_rat_draw.h" + +static void ChangeFlag(const char *, const char *, int, const char *); +static int pcb_act_ChangeSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); +static int pcb_act_Change2ndSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); + +/* --------------------------------------------------------------------------- */ + +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."; + +/* %start-doc actions ChangeClearSize + +If the solder mask is currently showing, this action changes the +solder mask clearance. If the mask is not showing, this action +changes the polygon clearance. + +%end-doc */ + +static int pcb_act_ChangeClearSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *delta = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_bool absolute; + pcb_coord_t value; + int type = PCB_TYPE_NONE; + void *ptr1, *ptr2, *ptr3; + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_gui->get_coords(_("Select an Object"), &x, &y); + type = pcb_search_screen(x, y, PCB_CHANGECLEARSIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(argv[1], "style") == 0) { + if ((type == PCB_TYPE_NONE) || (type == PCB_TYPE_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) + return 1; + 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_TYPE_NONE) + if (pcb_chg_obj_clear_size(type, ptr1, ptr2, ptr3, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + case F_SelectedVias: + if (pcb_chg_selected_clear_size(PCB_TYPE_VIA, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedPads: + if (pcb_chg_selected_clear_size(PCB_TYPE_PAD, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedPins: + if (pcb_chg_selected_clear_size(PCB_TYPE_PIN, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedLines: + if (pcb_chg_selected_clear_size(PCB_TYPE_LINE, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedArcs: + if (pcb_chg_selected_clear_size(PCB_TYPE_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; + } + } + 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 = square | octagon | thermal | join\n" "value = 0 | 1"; + +static const char pcb_acth_ChangeFlag[] = "Sets or clears flags on objects."; + +/* %start-doc actions ChangeFlag + +Toggles the given flag on the indicated object(s). The flag may be +one of the flags listed above (square, octagon, 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. + +%end-doc */ + +static int pcb_act_ChangeFlag(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *flag = PCB_ACTION_ARG(1); + int value = argc > 2 ? atoi(argv[2]) : -1; + if (value != 0 && value != 1) + PCB_ACT_FAIL(ChangeFlag); + + ChangeFlag(function, flag, value, "ChangeFlag"); + 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, "square") == 0) { + set_object = value ? pcb_set_obj_square : pcb_clr_obj_square; + set_selected = value ? pcb_set_selected_square : pcb_clr_selected_square; + } + else if (PCB_NSTRCMP(flag_name, "octagon") == 0) { + set_object = value ? pcb_set_obj_octagon : pcb_clr_obj_octagon; + set_selected = value ? pcb_set_selected_octagon : pcb_clr_selected_octagon; + } + else 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_gui->get_coords("Click on object to change", &x, &y); + + if ((type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + if (set_object(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedVias: + if (set_selected(PCB_TYPE_VIA)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (set_selected(PCB_TYPE_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPads: + if (set_selected(PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedLines: + if (set_selected(PCB_TYPE_LINE)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedTexts: + if (set_selected(PCB_TYPE_TEXT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedNames: + if (set_selected(PCB_TYPE_ELEMENT_NAME)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedElements: + if (set_selected(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (set_selected(PCB_CHANGESIZE_TYPES)) + pcb_board_set_changed_flag(pcb_true); + break; + } +} + +/* --------------------------------------------------------------------------- */ + +static const char changehold_syntax[] = "ChangeHole(ToggleObject|Object|SelectedVias|Selected)"; + +static const char changehold_help[] = "Changes the hole flag of objects."; + +/* %start-doc actions ChangeHole + +The "hole flag" of a via determines whether the via is a +plated-through hole (not set), or an unplated hole (set). + +%end-doc */ + +static int pcb_act_ChangeHole(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_TYPE_VIA, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE && pcb_pin_change_hole((pcb_pin_t *) ptr3)) + pcb_undo_inc_serial(); + break; + } + + case F_SelectedVias: + case F_Selected: + if (pcb_chg_selected_hole()) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangePaste[] = "ChangePaste(ToggleObject|Object|SelectedPads|Selected)"; + +static const char pcb_acth_ChangePaste[] = "Changes the no paste flag of objects."; + +/* %start-doc actions ChangePaste + +The "no paste flag" of a pad determines whether the solderpaste + stencil will have an opening for the pad (no set) or if there will be + no solderpaste on the pad (set). This is used for things such as + fiducial pads. + +%end-doc */ + +static int pcb_act_ChangePaste(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_TYPE_PAD, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE && pcb_pad_change_paste((pcb_pad_t *) ptr3)) + pcb_undo_inc_serial(); + break; + } + + case F_SelectedPads: + case F_Selected: + if (pcb_chg_selected_paste()) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +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."; + +/* %start-doc actions ChangeSize + +Call pcb_act_ChangeSize, ActionChangeDrillSize and pcb_act_ChangeClearSize +with the same arguments. If any of them did not fail, return success. +%end-doc */ + +static int pcb_act_ChangeSizes(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int a, b, c; + pcb_undo_save_serial(); + a = pcb_act_ChangeSize(argc, argv, x, y); + pcb_undo_restore_serial(); + b = pcb_act_Change2ndSize(argc, argv, x, y); + pcb_undo_restore_serial(); + c = pcb_act_ChangeClearSize(argc, argv, x, y); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + return !(!a || !b || !c); +} + +/* --------------------------------------------------------------------------- */ + +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."; + +/* %start-doc actions ChangeSize + +For lines and arcs, this changes the width. For pins and vias, this +changes the overall diameter of the copper annulus. For pads, this +changes the width and, indirectly, the length. For texts and names, +this changes the scaling factor. For elements, this changes the width +of the silk layer lines and arcs for this element. + +%end-doc */ + +static int pcb_act_ChangeSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *delta = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_bool absolute; /* indicates if absolute size is given */ + pcb_coord_t value; + int type = PCB_TYPE_NONE, tostyle = 0; + void *ptr1, *ptr2, *ptr3; + + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_gui->get_coords("Click on object to change size of", &x, &y); + type = pcb_search_screen(x, y, PCB_CHANGESIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(argv[1], "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_TYPE_NONE) + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + 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: + if (pcb_chg_selected_size(PCB_TYPE_VIA, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_chg_selected_size(PCB_TYPE_PIN, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPads: + if (pcb_chg_selected_size(PCB_TYPE_PAD, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedArcs: + if (pcb_chg_selected_size(PCB_TYPE_ARC, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedLines: + if (pcb_chg_selected_size(PCB_TYPE_LINE, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedTexts: + if (pcb_chg_selected_size(PCB_TYPE_TEXT, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedNames: + if (pcb_chg_selected_size(PCB_TYPE_ELEMENT_NAME, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedElements: + if (pcb_chg_selected_size(PCB_TYPE_ELEMENT, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + 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; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char changedrillsize_syntax[] = + "ChangeDrillSize(Object, delta|style)\n" "ChangeDrillSize(SelectedPins|SelectedVias|Selected|SelectedObjects, delta|style)"; + +static const char changedrillsize_help[] = "Changes the drilling hole size of objects."; + +/* %start-doc actions ChangeDrillSize + +%end-doc */ + +static int pcb_act_Change2ndSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *delta = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + int type = PCB_TYPE_NONE; + void *ptr1, *ptr2, *ptr3; + + pcb_bool absolute; + pcb_coord_t value; + + if (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_gui->get_coords(_("Select an Object"), &x, &y); + type = pcb_search_screen(x, y, PCB_CHANGE2NDSIZE_TYPES, &ptr1, &ptr2, &ptr3); + } + + if (strcmp(argv[1], "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_TYPE_NONE) + if (pcb_chg_obj_2nd_size(type, ptr1, ptr2, ptr3, value, absolute, pcb_true)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedVias: + if (pcb_chg_selected_2nd_size(PCB_TYPE_VIA, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_chg_selected_2nd_size(PCB_TYPE_PIN, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_2nd_size(PCB_TYPEMASK_PIN, value, absolute)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangePinName[] = "ChangePinName(ElementName,PinNumber,PinName)"; + +static const char pcb_acth_ChangePinName[] = "Sets the name of a specific pin on a specific element."; + +/* %start-doc actions ChangePinName + +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) +@end example + +%end-doc */ + +static int pcb_act_ChangePinName(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int changed = 0; + const char *refdes, *pinnum, *pinname; + + if (argc != 3) { + PCB_ACT_FAIL(ChangePinName); + } + + refdes = argv[0]; + pinnum = argv[1]; + pinname = argv[2]; + + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_NSTRCMP(refdes, PCB_ELEM_NAME_REFDES(element)) == 0) { + PCB_PIN_LOOP(element); + { + if (PCB_NSTRCMP(pinnum, pin->Number) == 0) { + pcb_undo_add_obj_to_change_name(PCB_TYPE_PIN, NULL, NULL, pin, pin->Name); + /* + * Note: we can't free() pin->Name first because + * it is used in the undo list + */ + pin->Name = pcb_strdup(pinname); + pcb_board_set_changed_flag(pcb_true); + changed = 1; + } + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + if (PCB_NSTRCMP(pinnum, pad->Number) == 0) { + pcb_undo_add_obj_to_change_name(PCB_TYPE_PAD, NULL, NULL, pad, pad->Name); + /* + * Note: we can't free() pad->Name first because + * it is used in the undo list + */ + pad->Name = pcb_strdup(pinname); + pcb_board_set_changed_flag(pcb_true); + changed = 1; + } + } + PCB_END_LOOP; + } + } + 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(); + } + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeName[] = "ChangeName(Object)\n" "ChangeName(Object|\"Number\")\n" "ChangeName(Layout|Layer)"; + +static const char pcb_acth_ChangeName[] = "Sets the name (or pin number) of objects."; + +/* %start-doc actions ChangeName + +@table @code + +@item Object +Changes the name of the element under the cursor. + +@item Layout +Changes the name of the layout. This is printed on the fab drawings. + +@item Layer +Changes the name of the currently active layer. + +@end table + +%end-doc */ + +int pcb_act_ChangeName(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *pinnums = PCB_ACTION_ARG(1); + char *name; + int pinnum; + + if (function) { + switch (pcb_funchash_get(function, NULL)) { + /* change the name of an object */ + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGENAME_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + pcb_undo_save_serial(); + if ((pinnums != NULL) && (pcb_strcasecmp(pinnums, "Number") == 0)) + pinnum = 1; + else + pinnum = 0; + if (pcb_chg_obj_name_query(type, ptr1, ptr2, ptr3, pinnum)) { + pcb_redraw(); + pcb_board_set_changed_flag(pcb_true); + pcb_event(PCB_EVENT_RUBBER_RENAME, "ipppi", type, ptr1, ptr2, ptr3, pinnum); + } + } + break; + } + + /* change the layout's name */ + case F_Layout: + name = pcb_gui->prompt_for(_("Enter the layout name:"), PCB_EMPTY(PCB->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_gui->prompt_for(_("Enter the layer name:"), PCB_EMPTY(CURRENT->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; + } + } + 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."; + +/* %start-doc actions ChangeJoin + +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. + +%end-doc */ + +static int pcb_act_ChangeJoin(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGEJOIN_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + 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_TYPE_LINE)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedArcs: + if (pcb_chg_selected_join(PCB_TYPE_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; + } + } + 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 elements."; + +/* %start-doc actions ChangeNonetlist + +Note that @code{Pins} means both pins and pads. + +@pinshapes + +%end-doc */ + +static int pcb_act_ChangeNonetlist(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + case F_Element: + { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_gui->get_coords(_("Select an Element"), &x, &y); + + 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_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeSquare[] = + "ChangeSquare(ToggleObject)\n" "ChangeSquare(SelectedElements|SelectedPins)\n" "ChangeSquare(Selected|SelectedObjects)"; + +static const char pcb_acth_ChangeSquare[] = "Changes the square flag of pins and pads."; + +/* %start-doc actions ChangeSquare + +Note that @code{Pins} means both pins and pads. + +@pinshapes + +%end-doc */ + +static int pcb_act_ChangeSquare(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + + ptr3 = NULL; + type = pcb_search_screen(x, y, PCB_CHANGESQUARE_TYPES, &ptr1, &ptr2, &ptr3); + + if (ptr3 != NULL) { + int qstyle = PCB_FLAG_SQUARE_GET((pcb_pin_t *) ptr3); + qstyle++; + if (qstyle > 17) + qstyle = 0; + if (type != PCB_TYPE_NONE) + if (pcb_chg_obj_square(type, ptr1, ptr2, ptr3, qstyle)) + pcb_board_set_changed_flag(pcb_true); + } + break; + } + + case F_SelectedElements: + if (pcb_chg_selected_square(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_chg_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetSquare[] = "SetSquare(ToggleObject|SelectedElements|SelectedPins)"; + +static const char pcb_acth_SetSquare[] = "sets the square-flag of objects."; + +/* %start-doc actions SetSquare + +Note that @code{Pins} means pins and pads. + +@pinshapes + +%end-doc */ + +static int pcb_act_SetSquare(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function && *function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGESQUARE_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_set_obj_square(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedElements: + if (pcb_set_selected_square(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_set_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_set_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ClearSquare[] = "ClearSquare(ToggleObject|SelectedElements|SelectedPins)"; + +static const char pcb_acth_ClearSquare[] = "Clears the square-flag of pins and pads."; + +/* %start-doc actions ClearSquare + +Note that @code{Pins} means pins and pads. + +@pinshapes + +%end-doc */ + +static int pcb_act_ClearSquare(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function && *function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGESQUARE_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_clr_obj_square(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedElements: + if (pcb_clr_selected_square(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_clr_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_clr_selected_square(PCB_TYPE_PIN | PCB_TYPE_PAD)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ChangeOctagon[] = + "ChangeOctagon(Object|ToggleObject|SelectedObjects|Selected)\n" "ChangeOctagon(SelectedElements|SelectedPins|SelectedVias)"; + +static const char pcb_acth_ChangeOctagon[] = "Changes the octagon-flag of pins and vias."; + +/* %start-doc actions ChangeOctagon + +@pinshapes + +%end-doc */ + +static int pcb_act_ChangeOctagon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGEOCTAGON_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_chg_obj_octagon(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedElements: + if (pcb_chg_selected_octagon(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_chg_selected_octagon(PCB_TYPE_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedVias: + if (pcb_chg_selected_octagon(PCB_TYPE_VIA)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_chg_selected_octagon(PCB_TYPEMASK_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetOctagon[] = "SetOctagon(Object|ToggleObject|SelectedElements|Selected)"; + +static const char pcb_acth_SetOctagon[] = "Sets the octagon-flag of objects."; + +/* %start-doc actions SetOctagon + +@pinshapes + +%end-doc */ + +static int pcb_act_SetOctagon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGEOCTAGON_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_set_obj_octagon(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedElements: + if (pcb_set_selected_octagon(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_set_selected_octagon(PCB_TYPE_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedVias: + if (pcb_set_selected_octagon(PCB_TYPE_VIA)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_set_selected_octagon(PCB_TYPEMASK_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ClearOctagon[] = + "ClearOctagon(ToggleObject|Object|SelectedObjects|Selected)\n" "ClearOctagon(SelectedElements|SelectedPins|SelectedVias)"; + +static const char pcb_acth_ClearOctagon[] = "Clears the octagon-flag of pins and vias."; + +/* %start-doc actions ClearOctagon + +@pinshapes + +%end-doc */ + +static int pcb_act_ClearOctagon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleObject: + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGEOCTAGON_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_clr_obj_octagon(type, ptr1, ptr2, ptr3)) + pcb_board_set_changed_flag(pcb_true); + break; + } + + case F_SelectedElements: + if (pcb_clr_selected_octagon(PCB_TYPE_ELEMENT)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedPins: + if (pcb_clr_selected_octagon(PCB_TYPE_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_SelectedVias: + if (pcb_clr_selected_octagon(PCB_TYPE_VIA)) + pcb_board_set_changed_flag(pcb_true); + break; + + case F_Selected: + case F_SelectedObjects: + if (pcb_clr_selected_octagon(PCB_TYPEMASK_PIN)) + pcb_board_set_changed_flag(pcb_true); + break; + } + } + 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 pins or vias 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"; + +/* %start-doc actions SetThermal + +This changes how/whether pins or vias connect to any rectangle or polygon +on the current layer. The first argument can specify one object, or all +selected pins, or all selected vias, or all selected pins and vias. +The second argument specifies the style of connection. +There are 5 possibilities: +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. + +Pins and Vias may have thermals whether or not there is a polygon available +to connect with. However, they will have no effect without the polygon. +%end-doc */ + +static int pcb_act_SetThermal(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *style = PCB_ACTION_ARG(1); + void *ptr1, *ptr2, *ptr3; + int type, kind; + int err = 0; + pcb_coord_t gx, gy; + + 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_gui->get_coords("Click on object for SetThermal", &gx, &gy); + if ((type = pcb_search_screen(gx, gy, PCB_CHANGETHERMAL_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, kind, INDEXOFCURRENT); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + case F_SelectedPins: + pcb_chg_selected_thermals(PCB_TYPE_PIN, kind, INDEXOFCURRENT); + break; + case F_SelectedVias: + pcb_chg_selected_thermals(PCB_TYPE_VIA, 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) + 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 = square | octagon | thermal | join"; + +static const char pcb_acth_SetFlag[] = "Sets flags on objects."; + +/* %start-doc actions SetFlag + +Turns the given flag on, regardless of its previous setting. See +@code{ChangeFlag}. + +@example +SetFlag(SelectedPins,thermal) +@end example + +%end-doc */ + +static int pcb_act_SetFlag(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *flag = PCB_ACTION_ARG(1); + ChangeFlag(function, flag, 1, "SetFlag"); + 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 = square | octagon | thermal | join"; + +static const char pcb_acth_ClrFlag[] = "Clears flags on objects."; + +/* %start-doc actions ClrFlag + +Turns the given flag off, regardless of its previous setting. See +@code{ChangeFlag}. + +@example +ClrFlag(SelectedLines,join) +@end example + +%end-doc */ + +static int pcb_act_ClrFlag(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *flag = PCB_ACTION_ARG(1); + ChangeFlag(function, flag, 0, "ClrFlag"); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetValue[] = "SetValue(Grid|Line|LineSize|Text|TextScale|ViaDrillingHole|Via|ViaSize, delta)"; + +static const char pcb_acth_SetValue[] = "Change various board-wide values and sizes."; + +/* %start-doc actions SetValue + +@table @code + +@item ViaDrillingHole +Changes the diameter of the drill for new vias. + +@item Grid +Sets the grid spacing. + +@item Line +@item LineSize +Changes the thickness of new lines. + +@item Via +@item ViaSize +Changes the diameter of new vias. + +@item Text +@item TextScale +Changes the size of new text. + +@end table + +%end-doc */ + +static int pcb_act_SetValue(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *val = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_bool absolute; /* flag for 'absolute' value */ + double value; + int err = 0; + + if (function && val) { + value = pcb_get_value(val, units, &absolute, NULL); + switch (pcb_funchash_get(function, NULL)) { + case F_ViaDrillingHole: + pcb_board_set_via_drilling_hole(absolute ? value : value + conf_core.design.via_drilling_hole, pcb_false); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case F_Grid: + if (absolute) + pcb_board_set_grid(value, pcb_false); + else { + /* On the way down, short against the minimum + * PCB drawing unit */ + if ((value + PCB->Grid) < 1) + pcb_board_set_grid(1, pcb_false); + else if (PCB->Grid == 1) + pcb_board_set_grid(value, pcb_false); + else + pcb_board_set_grid(value + PCB->Grid, pcb_false); + } + 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_Via: + case F_ViaSize: + pcb_board_set_via_size(absolute ? value : value + conf_core.design.via_thickness, pcb_false); + 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) + 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 int pcb_act_ChangeAngle(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *prim = PCB_ACTION_ARG(1); + const char *delta = PCB_ACTION_ARG(2); + pcb_bool absolute; /* indicates if absolute size is given */ + double value; + int type = PCB_TYPE_NONE, which; + void *ptr1, *ptr2, *ptr3; + + 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 (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_gui->get_coords("Click on object to change angle of", &x, &y); + 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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + 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_TYPE_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; + } + } + 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 int pcb_act_ChangeRadius(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *prim = PCB_ACTION_ARG(1); + const char *delta = PCB_ACTION_ARG(2); + const char *units = PCB_ACTION_ARG(3); + pcb_bool absolute; /* indicates if absolute size is given */ + double value; + int type = PCB_TYPE_NONE, which; + void *ptr1, *ptr2, *ptr3; + + 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 (function && delta) { + int funcid = pcb_funchash_get(function, NULL); + + if (funcid == F_Object) { + pcb_coord_t x, y; + pcb_gui->get_coords("Click on object to change radius of", &x, &y); + 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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + 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_TYPE_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; + } + } + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +pcb_hid_action_t change_action_list[] = { + {"ChangeAngle", 0, pcb_act_ChangeAngle, + pcb_acth_ChangeAngle, pcb_acts_ChangeAngle} + , + {"ChangeClearSize", 0, pcb_act_ChangeClearSize, + pcb_acth_ChangeClearSize, pcb_acts_ChangeClearSize} + , + {"ChangeDrillSize", 0, pcb_act_Change2ndSize, + changedrillsize_help, changedrillsize_syntax} + , + {"ChangeHole", 0, pcb_act_ChangeHole, + changehold_help, changehold_syntax} + , + {"ChangeJoin", 0, pcb_act_ChangeJoin, + pcb_acth_ChangeJoin, pcb_acts_ChangeJoin} + , + {"ChangeName", 0, pcb_act_ChangeName, + pcb_acth_ChangeName, pcb_acts_ChangeName} + , + {"ChangePaste", 0, pcb_act_ChangePaste, + pcb_acth_ChangePaste, pcb_acts_ChangePaste} + , + {"ChangePinName", 0, pcb_act_ChangePinName, + pcb_acth_ChangePinName, pcb_acts_ChangePinName} + , + {"ChangeRadius", 0, pcb_act_ChangeRadius, + pcb_acth_ChangeRadius, pcb_acts_ChangeRadius} + , + {"ChangeSize", 0, pcb_act_ChangeSize, + pcb_acth_ChangeSize, pcb_acts_ChangeSize} + , + {"ChangeSizes", 0, pcb_act_ChangeSizes, + pcb_acth_ChangeSizes, pcb_acts_ChangeSizes} + , + {"ChangeNonetlist", 0, pcb_act_ChangeNonetlist, + pcb_acth_ChangeNonetlist, pcb_acts_ChangeNonetlist} + , + {"ChangeSquare", 0, pcb_act_ChangeSquare, + pcb_acth_ChangeSquare, pcb_acts_ChangeSquare} + , + {"ChangeOctagon", 0, pcb_act_ChangeOctagon, + pcb_acth_ChangeOctagon, pcb_acts_ChangeOctagon} + , + {"ChangeFlag", 0, pcb_act_ChangeFlag, + pcb_acth_ChangeFlag, pcb_acts_ChangeFlag} + , + {"ClearSquare", 0, pcb_act_ClearSquare, + pcb_acth_ClearSquare, pcb_acts_ClearSquare} + , + {"ClearOctagon", 0, pcb_act_ClearOctagon, + pcb_acth_ClearOctagon, pcb_acts_ClearOctagon} + , + {"SetSquare", 0, pcb_act_SetSquare, + pcb_acth_SetSquare, pcb_acts_SetSquare} + , + {"SetOctagon", 0, pcb_act_SetOctagon, + pcb_acth_SetOctagon, pcb_acts_SetOctagon} + , + {"SetThermal", 0, pcb_act_SetThermal, + pcb_acth_SetThermal, pcb_acts_SetThermal} + , + {"SetValue", 0, pcb_act_SetValue, + pcb_acth_SetValue, pcb_acts_SetValue} + , + {"SetFlag", 0, pcb_act_SetFlag, + pcb_acth_SetFlag, pcb_acts_SetFlag} + , + {"ClrFlag", 0, pcb_act_ClrFlag, + pcb_acth_ClrFlag, pcb_acts_ClrFlag} +}; + +PCB_REGISTER_ACTIONS(change_action_list, NULL) Index: tags/1.2.7/src/clip.c =================================================================== --- tags/1.2.7/src/clip.c (nonexistent) +++ tags/1.2.7/src/clip.c (revision 13657) @@ -0,0 +1,112 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "config.h" +#include "clip.h" + +#warning TODO: move this to lib_hid_common + +/* Clip the line to the clipBox + * return pcb_true if something to be drawn + * pcb_false if the whole thing is clipped + */ +pcb_bool pcb_line_clip(double minx, double miny, double maxx, double maxy, double *x1, double *y1, double *x2, double *y2, double margin) +{ + double d, r; + + minx -= margin; + miny -= margin; + maxx += margin; + maxy += margin; + + /* clip first point on left side */ + if (*x1 < minx) { + if (*x2 < minx) + return pcb_false; + d = *x2 - *x1; + r = (minx - *x1) / d; + *x1 = minx; + *y1 += r * (*y2 - *y1); + } + /* clip second point on left side */ + if (*x2 < minx) { + d = *x1 - *x2; + r = (minx - *x2) / d; + *x2 = minx; + *y2 += r * (*y1 - *y2); + } + /* clip first point on right side */ + if (*x1 > maxx) { + if (*x2 > maxx) + return pcb_false; + d = *x2 - *x1; + r = (maxx - *x1) / d; + *x1 = maxx; + *y1 += r * (*y2 - *y1); + } + /* clip second point on right side */ + if (*x2 > maxx) { + d = *x1 - *x2; + r = (maxx - *x2) / d; + *x2 = maxx; + *y2 += r * (*y1 - *y2); + } + + /* clip first point on top */ + if (*y1 < miny) { + if (*y2 < miny) + return pcb_false; + d = *y2 - *y1; + r = (miny - *y1) / d; + *y1 = miny; + *x1 += r * (*x2 - *x1); + } + /* clip second point on top */ + if (*y2 < miny) { + d = *y1 - *y2; + r = (miny - *y2) / d; + *y2 = miny; + *x2 += r * (*x1 - *x2); + } + /* clip first point on bottom */ + if (*y1 > maxy) { + if (*y2 > maxy) + return pcb_false; + d = *y2 - *y1; + r = (maxy - *y1) / d; + *y1 = maxy; + *x1 += r * (*x2 - *x1); + } + /* clip second point on top */ + if (*y2 > maxy) { + d = *y1 - *y2; + r = (maxy - *y2) / d; + *y2 = maxy; + *x2 += r * (*x1 - *x2); + } + return pcb_true; +} Index: tags/1.2.7/src/clip.h =================================================================== --- tags/1.2.7/src/clip.h (nonexistent) +++ tags/1.2.7/src/clip.h (revision 13657) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_CLIP_H +#define PCB_CLIP_H + +#include "global_typedefs.h" + +/* Clip X,Y to the given bounding box, plus a margin. Returns pcb_true if + there is something left to be drawn. */ +pcb_bool pcb_line_clip(double minx, double miny, double maxx, double maxy, + double *x1, double *y1, double *x2, double *y2, double margin); + +#endif Index: tags/1.2.7/src/compat_cc.h =================================================================== --- tags/1.2.7/src/compat_cc.h (nonexistent) +++ tags/1.2.7/src/compat_cc.h (revision 13657) @@ -0,0 +1,71 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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/1.2.7/src/compat_fs.c =================================================================== --- tags/1.2.7/src/compat_fs.c (nonexistent) +++ tags/1.2.7/src/compat_fs.c (revision 13657) @@ -0,0 +1,319 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* misc functions used by several modules */ + +#include "config.h" + +#include "compat_inc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "compat_fs.h" +#include "compat_misc.h" +#include "compat_nls.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); +} + +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/1.2.7/src/compat_fs.h =================================================================== --- tags/1.2.7/src/compat_fs.h (nonexistent) +++ tags/1.2.7/src/compat_fs.h (revision 13657) @@ -0,0 +1,25 @@ +/* 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); + +int pcb_mkdir(const char *path, int mode); + +/* 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 path is a directory */ +int pcb_is_dir(const char *path); + +/* Return non-zero if fn is an absolute path */ +int pcb_is_path_abs(const char *fn); Index: tags/1.2.7/src/compat_inc.h.in =================================================================== --- tags/1.2.7/src/compat_inc.h.in (nonexistent) +++ tags/1.2.7/src/compat_inc.h.in (revision 13657) @@ -0,0 +1,47 @@ +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@ +@] + +put /tmpasm/IFS {\n} +uniq /local/pcb/compat_inc +gsub /local/pcb/compat_inc {\\\\n *} {\n} + + +print [@ +/*** DO NOT EDIT - automatically generated by scconfig ***/ + +#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/1.2.7/src/compat_lrealpath.c =================================================================== --- tags/1.2.7/src/compat_lrealpath.c (nonexistent) +++ tags/1.2.7/src/compat_lrealpath.c (revision 13657) @@ -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/1.2.7/src/compat_lrealpath.h =================================================================== --- tags/1.2.7/src/compat_lrealpath.h (nonexistent) +++ tags/1.2.7/src/compat_lrealpath.h (revision 13657) @@ -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/1.2.7/src/compat_misc.c =================================================================== --- tags/1.2.7/src/compat_misc.c (nonexistent) +++ tags/1.2.7/src/compat_misc.c (revision 13657) @@ -0,0 +1,201 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +#include "compat_inc.h" +#include "config.h" + +#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 + return -1; +#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 +# error pcb_ms_sleep(): no milisecond sleep on this host. +# endif +#endif +} + +int pcb_fileno(FILE *f) +{ + return PCB_HOST_FILENO(f); +} Index: tags/1.2.7/src/compat_misc.h =================================================================== --- tags/1.2.7/src/compat_misc.h (nonexistent) +++ tags/1.2.7/src/compat_misc.h (revision 13657) @@ -0,0 +1,61 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +#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); + +int pcb_fileno(FILE *f); + +#endif /* PCB_COMPAT_MISC_H */ Index: tags/1.2.7/src/compat_nls.h =================================================================== --- tags/1.2.7/src/compat_nls.h (nonexistent) +++ tags/1.2.7/src/compat_nls.h (revision 13657) @@ -0,0 +1,56 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_COMPAT_NLS +#define PCB_COMPAT_NLS + +/* Internationalization support. */ +#ifdef ENABLE_NLS +# include +# define _(S) gettext(S) +# if defined(gettext_noop) +# define N_(S) gettext_noop(S) +# else +# define N_(S) S +# endif +# ifdef LOCALEDIR +# define pcb_setlocale setlocale +# else +# define pcb_setlocale(a, b) +# endif +#else +# define _(S) S +# define N_(S) S +# define textdomain(S) (S) +# define gettext(S) (S) +# define dgettext(D, S) (S) +# define dcgettext(D, S, T) (S) +# define bindtextdomain(D, Dir) (D) +# define pcb_setlocale(a, b) +#endif /* ENABLE_NLS */ + +#endif Index: tags/1.2.7/src/conf.c =================================================================== --- tags/1.2.7/src/conf.c (nonexistent) +++ tags/1.2.7/src/conf.c (revision 13657) @@ -0,0 +1,1951 @@ +/* + * 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. + * + */ + +#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" + +/* conf list node's name */ +const char *conf_list_name = "pcb-rnd-conf-v1"; +static const char *conf_user_fn = "~/" DOT_PCB_RND "/pcb-conf.lht"; + +lht_doc_t *conf_root[CFR_max_alloc]; +int conf_root_lock[CFR_max_alloc]; +int conf_lht_dirty[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_doc_t *conf_plugin;*/ + +static int conf_ignore_old_paths(const char *path) +{ + static const char *ignores[] = { "editor/show_mask", "editor/show_paste", NULL }; + const char **i; + for(i = ignores; *i != NULL; i++) + if (strcmp(path, *i) == 0) + return 1; + return 0; +} + +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_root[role] != NULL) { + lht_dom_uninit(conf_root[role]); + conf_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_root[role] = d; + return 0; +} + +int conf_load_as(conf_role_t role, const char *fn, int fn_is_text) +{ + lht_doc_t *d; + if (conf_root_lock[role]) + return -1; + if (conf_root[role] != NULL) { + lht_dom_uninit(conf_root[role]); + conf_root[role] = NULL; + } + if (fn_is_text) + d = pcb_hid_cfg_load_str(fn); + else + d = pcb_hid_cfg_load_lht(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); + free(efn); + fclose(f); + } + free(efn); + return -1; + } + + if (d->root == NULL) { + lht_node_t *prjroot, *confroot; + prjroot = lht_dom_node_alloc(LHT_HASH, "geda-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_root[role] = d; + return 0; + } + + if ((d->root->type == LHT_LIST) && (strcmp(d->root->name, "pcb-rnd-conf-v1") == 0)) { + conf_root[role] = d; + return 0; + } + + if ((d->root->type == LHT_HASH) && (strcmp(d->root->name, "geda-project-v1") == 0)) { + lht_node_t *confroot; + confroot = lht_tree_path_(d, d->root, "pcb-rnd-conf-v1", 1, 0, NULL); + if ((confroot != NULL) && (confroot->type == LHT_LIST) && (strcmp(confroot->name, "li:pcb-rnd-conf-v1") == 0)) { + conf_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_root[role] = d; + return 0; + } + + pcb_hid_cfg_error(d->root, "Root node must be either li:pcb-rnd-conf-v1 or ha:geda-project-v1\n"); + + if (d != NULL) + lht_dom_uninit(d); + return -1; +} + +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; + } +} + +static int conf_parse_increments(pcb_increments_t *inc, lht_node_t *node) +{ + lht_node_t *val; + + if (node->type != LHT_HASH) { + pcb_hid_cfg_error(node, "Increments need to be a hash\n"); + return -1; + } + +#define incload(field) \ + val = lht_dom_hash_get(node, #field); \ + if (val != NULL) {\ + if (val->type == LHT_TEXT) {\ + pcb_bool succ; \ + inc->field = pcb_get_value(val->data.text.value, NULL, NULL, &succ); \ + if (!succ) \ + pcb_hid_cfg_error(node, "invalid numeric value in increment field " #field ": %s\n", val->data.text.value); \ + } \ + else\ + pcb_hid_cfg_error(node, "increment field " #field " needs to be a text node\n"); \ + } + + incload(grid); + incload(grid_min); + incload(grid_max); + incload(size); + incload(size_min); + incload(size_max); + incload(line); + incload(line_min); + incload(line_max); + incload(clear); + incload(clear_min); + incload(clear_max); + +#undef incload + return 0; +} + +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_INCREMENTS: + return conf_parse_increments(&(dst->increments[idx]), err_node); + case CFN_COLOR: + dst->color[idx] = text; /* let the HID check validity to support flexibility of the format */ + 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_PCB_MOVE(CFN_INCREMENTS, increments); + } + } +#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 (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 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; + int res = 0; + conf_listitem_t *i; + + if ((pol == POL_DISABLE) || (pol == POL_invalid)) + return 0; + + if (pol == POL_OVERWRITE) { + /* overwrite the whole list: make it empty then append new elements */ + while((i = conflist_first(dest->val.list)) != NULL) + conflist_remove(i); + } + + 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->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; + } + + switch(pol) { + case POL_PREPEND: + conflist_insert(dest->val.list, i); + dest->used |= 1; + break; + case POL_APPEND: + case POL_OVERWRITE: + conflist_append(dest->val.list, i); + dest->used |= 1; + break; + case POL_DISABLE: case POL_invalid: return 0; /* compiler warning */ + } + } + else { + pcb_hid_cfg_error(s, "List item must be text\n"); + res = -1; + } + } + return res; +} + +int conf_merge_patch_recurse(lht_node_t *sect, int default_prio, conf_policy_t default_policy, const char *path_prefix); + +int conf_merge_patch_item(const char *path, lht_node_t *n, int default_prio, conf_policy_t default_policy) +{ + conf_native_t *target = conf_get_field(path); + int res = 0; + switch(n->type) { + case LHT_TEXT: + if (target == NULL) { + if ((strncmp(path, "plugins/", 8) != 0) && (strncmp(path, "utils/", 6) != 0) && !conf_ignore_old_paths(path)) /* it is normal to have configuration for plugins and utils not loaded - ignore these */ + pcb_hid_cfg_error(n, "conf error: lht->bin conversion: can't find path '%s' - check your lht!\n", path); + break; + } + 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, 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) { + if ((strncmp(path, "plugins/", 8) != 0) && (strncmp(path, "utils/", 6) != 0))/* it is normal to have configuration for plugins and utils not loaded - ignore these */ + pcb_hid_cfg_error(n, "conf error: lht->bin conversion: can't find path '%s' - check your lht; may it be that it should be a hash instead of a list?\n", path); + } + 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: +#warning 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, 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; + + 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); + memcpy(pathe, n->name, nl); + namee = pathe+nl; + *namee = '\0'; + res |= conf_merge_patch_item(path, n, default_prio, default_policy); + } + return res; +} + +int conf_merge_patch(lht_node_t *root, 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, gprio, gpolicy, n->name); + + return 0; +} + +typedef struct { + 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(int role, lht_node_t *subtree_parent_root, lht_node_t *subtree_root) +{ + merge_subtree_t *m; + + m = vmst_alloc_append(&merge_subtree, 1); + 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; +} + +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, *r, *r2; + if (conf_root[n] == NULL) + continue; + + cr = conf_lht_get_confroot(conf_root[n]->root); + if (cr == NULL) + continue; + + 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(n, r, r2); + } + else + add_subtree(n, r, r); + } + } + + 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].prio, merge_subtree.array[n].policy); + else + ret |= conf_merge_patch(merge_subtree.array[n].subtree, 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_INCREMENTS: clr(increments); 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; + } + 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_); + } + + /* It may be a field of an increment, truncate last portion */ + if (n == NULL) { + field = strrchr(path_, '/'); + if (field == NULL) { + free(path_); + return; + } + *field = '\0'; + n = conf_get_field(path_); + if (n->type != CFN_INCREMENTS) + n = NULL; + } + + /* 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++; +} + +static lht_node_t *conf_lht_get_first_(lht_node_t *cwd, 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 (ov == NULL) { + lht_node_t *new_ov; + if (!create) + return NULL; + new_ov = lht_dom_node_alloc(LHT_HASH, "overwrite"); + 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_root[target] == NULL) + return NULL; + return conf_lht_get_first_(conf_root[target]->root, 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); + 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_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) +{ + int i; + lht_node_t *dln; + const char *pc, *try; + + /* get the lihata node for design/default_layer_name */ + conf_load_as(CFR_INTERNAL, conf_internal, 1); + dln = conf_lht_get_at(CFR_INTERNAL, "design/default_layer_name", 1); + assert(dln != NULL); + assert(dln->type == LHT_LIST); + dln = dln->data.list.first; + + /* Set up default layer names - make sure there are enough layers (over the hardwired ones, if any) */ + for (i = 0; i < PCB_MAX_LAYER; i++) { + char buf[20]; + if (dln == NULL) { + sprintf(buf, "signal%d", i + 1); + if (conf_set_dry(CFR_INTERNAL, "design/default_layer_name", i, buf, POL_OVERWRITE) != 0) + printf("Can't set layer name\n"); + } + else + dln = dln->next; + } + + /* 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_root[CFR_USER] == NULL) + conf_reset(CFR_USER, conf_user_fn); +} + +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)); + + 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)); + 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) +{ + char *path, *basename, *next, *last, *sidx, *increment_field = NULL; + 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; + + 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) { + /* might be increments */ + increment_field = strrchr(path, '/'); + if (increment_field == NULL) { + free(path); + return -1; + } + *increment_field = '\0'; + nat = conf_get_field(path); + if ((nat == NULL) || (nat->type != CFN_INCREMENTS)) { + free(path); + return -1; + } + *increment_field = '/'; + increment_field++; + } + + + if (conf_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(target, 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_root[target], cwd, last, 1, 0, NULL); + if (nn == NULL) { + if (new_val == NULL) { + free(path); + return 0; + } + if (conf_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_root[target], cwd, basename, 1, 0, NULL); + if (nn == NULL) { + if (conf_root_lock[target]) { + free(path); + return -1; + } + nn = lht_dom_node_alloc(ty, basename); + 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_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); + 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); + 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 */ + ret = conf_set(CFR_CLI, arg, -1, val, pol); + if (ret != 0) + *why = "invalid config path"; + + free(arg); + return ret; +} + +void 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; +} + +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: + case CFN_INCREMENTS: + strcpy(s, " ???"); + 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) { +#warning CONF TODO: 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) { + 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 */ + *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_root_lock[target] = 1; +} + +void conf_unlock(conf_role_t target) +{ + conf_root_lock[target] = 0; +} + +int conf_islocked(conf_role_t target) +{ + return conf_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_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_root[target] != NULL) + lht_dom_uninit(conf_root[target]); + + conf_root[target] = lht_dom_init(); + lht_dom_loc_newfile(conf_root[target], source_fn); + conf_root[target]->root = lht_dom_node_alloc(LHT_LIST, conf_list_name); + conf_root[target]->root->doc = conf_root[target]; + n = lht_dom_node_alloc(LHT_HASH, "overwrite"); + lht_dom_list_insert(conf_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], val->color[idx]); break; + case CFN_INCREMENTS: + { + pcb_increments_t *i = &val->increments[idx]; + ret += pfn(ctx, "{ grid=%$mS/%$mS/%$mS size=%$mS/%$mS/%$mS line=%$mS/%$mS/%$mS clear=%$mS/%$mS/%$mS}", + i->grid, i->grid_min, i->grid_max, + i->size, i->size_min, i->size_max, + i->line, i->line_min, i->line_max, + i->clear, i->clear_min, i->clear_max); + } + 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; + } + 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_pcb_hid_uninit(); + + for(n = 0; n < CFR_max_alloc; n++) + if (conf_root[n] != NULL) + lht_dom_uninit(conf_root[n]); + + conf_fields_foreach(e) { + conf_free_native(e->value); + htsp_delentry(conf_fields, e); + } + htsp_free(conf_fields); + + vmst_uninit(&merge_subtree); +} + +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); +} + +int pcb_conf_cmd_is_safe_(const char *path_, const char *value, const char **val_out, int msg) +{ + const char *reason; + conf_native_t *nd; + char *path, *s; + + if (val_out != NULL) + *val_out = NULL; + + if (value == NULL) + goto accept; + + path = pcb_strdup(path_); + for(s = path; *s != '\0'; s++) + if (*s == '.') + *s = '/'; + nd = conf_get_field(path); + free(path); + + if (nd == NULL) { + if (msg) + pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): invalid node path '%s' (looks like an internal error)\n", path_); + return 0; + } + + if (nd->array_size > 1) { + if (msg) + pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): invalid node path '%s' (it is an array)\n", path_); + return 0; + } + + switch(conf_lookup_role(nd->prop[0].src)) { + /* these are considered safe, because: */ + case CFR_INTERNAL: /* the attacker would have access to the source code and compilation, could place system() anyway */ + case CFR_SYSTEM: /* system admin - lets trust them */ + case CFR_USER: /* user config is written by the user, attackers have no better chance to overwrite that than overwriting the the shell's rc */ + case CFR_CLI: /* command line arguments: the user specified those; who has access to that potentially has access to the shell anyway */ + goto accept; + + /* these are considered unsafe, because: */ + case CFR_DEFAULTPCB: /* the default pcb path may be manipulated; the user has the chance to specify the command path setting from safe config files */ + reason = "default pcb"; break; + case CFR_ENV: /* env vars may be inherited from who-knows-where */ + reason = "env var"; break; + case CFR_PROJECT: /* malicous file prepared by the attacker */ + reason = "project file"; break; + case CFR_DESIGN: /* malicous file prepared by the attacker */ + reason = "board file"; break; + default: + reason = "unknown source"; + } + + if (msg) + pcb_message(PCB_MSG_ERROR, "pcb_conf_cmd_is_safe(): refusing to use the value of '%s' because it is from unsafe source %s\n", path_, reason); + return 0; + + accept:; + if (val_out != NULL) + *val_out = value; + return 1; +} Index: tags/1.2.7/src/conf.h =================================================================== --- tags/1.2.7/src/conf.h (nonexistent) +++ tags/1.2.7/src/conf.h (revision 13657) @@ -0,0 +1,375 @@ +/* + * 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. + * + */ + +#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 char * CFT_COLOR; +typedef conflist_t CFT_LIST; +typedef pcb_increments_t CFT_INCREMENTS; + +typedef enum { + CFN_STRING, + CFN_BOOLEAN, + CFN_INTEGER, /* signed long */ + CFN_REAL, /* double */ + CFN_COORD, + CFN_UNIT, + CFN_COLOR, + CFN_LIST, + CFN_INCREMENTS +} 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; + const char **color; + conflist_t *list; + pcb_increments_t *increments; + 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 *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 */ +void conf_load_all(const char *project_fn, const char *pcb_fn); + +/* 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); + +/* 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. */ +int conf_set_dry(conf_role_t target, const char *path_, int arr_idx, const char *new_val, conf_policy_t pol); + +/* 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 */ +void 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); \ + 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 *)cl); 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); + +/* Return 1 if the config node named in path is considered safe enough + to specify a command to execute - e.g. an attacker shouldn't be able to + inject commands in design files sent */ +int pcb_conf_cmd_is_safe_(const char *path, const char *value, const char **val_out, int msg); +#define pcb_conf_cmd_is_safe(path, val_out, msg) pcb_conf_cmd_is_safe_(#path, conf_core.path, val_out, msg) + +#endif Index: tags/1.2.7/src/conf_act.c =================================================================== --- tags/1.2.7/src/conf_act.c (nonexistent) +++ tags/1.2.7/src/conf_act.c (revision 13657) @@ -0,0 +1,336 @@ +/* + * 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. + * + */ + +#include "config.h" +#include "board.h" +#include "conf_core.h" +#include "route_style.h" +#include "error.h" +#include "hid.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 int pcb_act_Conf(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *cmd = argc > 0 ? argv[0] : 0; + + if ((PCB_NSTRCMP(cmd, "set") == 0) || (PCB_NSTRCMP(cmd, "delta") == 0)) { + const char *path, *val; + char valbuff[128]; + conf_policy_t pol = POL_OVERWRITE; + conf_role_t role = CFR_invalid; + int res; + + if (argc < 3) { + pcb_message(PCB_MSG_ERROR, "conf(set) needs at least two arguments"); + return 1; + } + if (argc > 3) { + role = conf_role_parse(argv[3]); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", argv[3]); + return 1; + } + } + if (argc > 4) { + pol = conf_policy_parse(argv[4]); + if (pol == POL_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid policy: '%s'", argv[4]); + return 1; + } + } + path = argv[1]; + val = argv[2]; + + if (cmd[0] == 'd') { + double d; + char *end; + conf_native_t *n = conf_get_field(argv[1]); + + if (n == 0) { + pcb_message(PCB_MSG_ERROR, "Can't delta-set '%s': no such path\n", argv[1]); + return 1; + } + + 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", argv[1]); + return 1; + } + 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", argv[1]); + return 1; + } + } + + if (role == CFR_invalid) { + conf_native_t *n = conf_get_field(argv[1]); + if (n == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid conf field '%s': no such path\n", argv[1]); + return 1; + } + res = conf_set_native(n, 0, val); + } + else + res = conf_set(role, path, -1, val, pol); + + if (res != 0) { + pcb_message(PCB_MSG_ERROR, "conf(set) failed.\n"); + return 1; + } + } + + else if (PCB_NSTRCMP(cmd, "iseq") == 0) { + const char *path, *val; + int res; + gds_t nval; + conf_native_t *n; + + if (argc != 3) { + pcb_message(PCB_MSG_ERROR, "conf(iseq) needs two arguments"); + return -1; + } + path = argv[1]; + val = argv[2]; + + n = conf_get_field(argv[1]); + if (n == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid conf field '%s' in iseq: no such path\n", path); + return -1; + } + + gds_init(&nval); + conf_print_native_field(conf_iseq_pf, &nval, 0, &n->val, n->type, NULL, 0); + res = !strcmp(nval.array, val); +/* printf("iseq: %s %s==%s %d\n", path, nval.array, val, res);*/ + gds_uninit(&nval); + + return res; + } + + else if (PCB_NSTRCMP(cmd, "toggle") == 0) { + conf_native_t *n = conf_get_field(argv[1]); + 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", argv[1]); + return 1; + } + if (n->type != CFN_BOOLEAN) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': not a boolean\n", argv[1]); + return 1; + } + if (n->used != 1) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': array size should be 1, not %d\n", argv[1], n->used); + return 1; + } + if (argc > 2) { + role = conf_role_parse(argv[2]); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", argv[2]); + return 1; + } + } + 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, argv[1], -1, new_value, POL_OVERWRITE); + + if (res != 0) { + pcb_message(PCB_MSG_ERROR, "Can not toggle '%s': failed to set new value\n", argv[1]); + return 1; + } + conf_update(argv[1], -1); + } + + else if (PCB_NSTRCMP(cmd, "reset") == 0) { + conf_role_t role; + role = conf_role_parse(argv[1]); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", argv[1]); + return 1; + } + conf_reset(role, ""); + conf_update(argv[1], -1); + } + + else { + pcb_message(PCB_MSG_ERROR, "Invalid conf command '%s'\n", argv[0]); + return 1; + } + return 0; +} + +/*------------ get/chk (check flag actions for menus) ------------------*/ +static const char GetStyle_syntax[] = "GetStyle()" ; +static const char GetStyle_help[] = "Return integer index (>=0) of the currently active style or -1 if no style is selected (== custom style)"; +static int pcb_act_GetStyle(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + return 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); +} + +static const char ChkMode_syntax[] = "ChkMode(expected_mode)" ; +static const char ChkMode_help[] = "Return 1 if the currently selected mode is the expected_mode"; +static int pcb_act_ChkMode(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ +#warning cleanup TODO: convert this to a compile-time hash; or make the toolbar configurable from the menu file + struct { + const char *name; + int mode; + } *m, modes[] = { + {"none", PCB_MODE_NO}, + {"arc", PCB_MODE_ARC}, + {"arrow", PCB_MODE_ARROW}, + {"copy", PCB_MODE_COPY}, + {"insertpoint", PCB_MODE_INSERT_POINT}, + {"line", PCB_MODE_LINE}, + {"lock", PCB_MODE_LOCK}, + {"move", PCB_MODE_MOVE}, + {"pastebuffer", PCB_MODE_PASTE_BUFFER}, + {"polygon", PCB_MODE_POLYGON}, + {"polygonhole", PCB_MODE_POLYGON_HOLE}, + {"rectangle", PCB_MODE_RECTANGLE}, + {"remove", PCB_MODE_REMOVE}, + {"rotate", PCB_MODE_ROTATE}, + {"rubberbandmove", PCB_MODE_RUBBERBAND_MOVE}, + {"text", PCB_MODE_TEXT}, + {"thermal", PCB_MODE_THERMAL}, + {"via", PCB_MODE_VIA}, + {NULL, 0} + }; + assert(argc == 1); + for(m = modes; m->name != NULL; m++) { + if (strcmp(m->name, argv[0]) == 0) + return conf_core.editor.mode == m->mode; + } + pcb_message(PCB_MSG_ERROR, "Unknown mode in ChkMode(): %s\n", argv[1]); + abort(); + return -1; +} + + +static const char ChkGridSize_syntax[] = + "ChkGridSize(expected_size)\n" + "ChkGridSize(none)\n" + ; +static const char ChkGridSize_help[] = "Return 1 if the currently selected grid matches the expected_size. If argument is \"none\" return 1 if there is no grid."; +static int pcb_act_ChkGridSize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + assert(argc == 1); + if (strcmp(argv[0], "none") == 0) + return PCB->Grid <= 300; + + return (PCB->Grid == pcb_get_value_ex(argv[0], NULL, NULL, NULL, NULL, NULL)); +} + +static const char ChkElementName_syntax[] = + "ChkElementName(1) - expect description\n" + "ChkElementName(2) - expect refdes\n" + "ChkElementName(3) - expect value\n" + ; +static const char ChkElementName_help[] = "Return 1 if currently shown element label (name) type matches the expected"; +static int pcb_act_ChkElementName(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int have, expected = argv[0][0] - '0'; + + assert(argc == 1); + if (conf_core.editor.description) have = 1; + else if (conf_core.editor.name_on_pcb) have = 2; + else have = 3; + + return expected == have; +} + +static const char ChkGridUnits_syntax[] = "ChkGridUnits(expected)"; +static const char ChkGridUnits_help[] = "Return 1 if currently selected grid unit matches the expected (normally mm or mil)"; +static int pcb_act_ChkGridUnits(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + assert(argc == 1); + return strcmp(conf_core.editor.grid_unit->suffix, argv[0]) == 0; +} + +static const char ChkBuffer_syntax[] = "ChkBuffer(idx)"; +static const char ChkBuffer_help[] = "Return 1 if currently selected buffer's index matches idx"; +static int pcb_act_ChkBuffer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int expected = argv[0][0] - '0'; + assert(argc == 1); + + return (conf_core.editor.buffer_number + 1) == expected; +} + +pcb_hid_action_t conf_action_list[] = { + {"conf", 0, pcb_act_Conf, + pcb_acth_Conf, pcb_acts_Conf} + , + {"GetStyle", 0, pcb_act_GetStyle, + GetStyle_help, GetStyle_syntax} + , + {"ChkMode", 0, pcb_act_ChkMode, + ChkMode_help, ChkMode_syntax} + , + {"ChkGridSize", 0, pcb_act_ChkGridSize, + ChkGridSize_help, ChkGridSize_syntax} + , + {"ChkElementName", 0, pcb_act_ChkElementName, + ChkElementName_help, ChkElementName_syntax} + , + {"ChkGridUnits", 0, pcb_act_ChkGridUnits, + ChkGridUnits_help, ChkGridUnits_syntax} + , + {"ChkBuffer", 0, pcb_act_ChkBuffer, + ChkBuffer_help, ChkBuffer_syntax} +}; + +PCB_REGISTER_ACTIONS(conf_action_list, NULL) Index: tags/1.2.7/src/conf_core.c =================================================================== --- tags/1.2.7/src/conf_core.c (nonexistent) +++ tags/1.2.7/src/conf_core.c (revision 13657) @@ -0,0 +1,59 @@ +#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_clamp(CFT_COORD, conf_core.design.max_width, PCB_MIN_SIZE, PCB_MAX_COORD); + conf_clamp(CFT_COORD, conf_core.design.max_height, PCB_MIN_SIZE, PCB_MAX_COORD); + 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/1.2.7/src/conf_core.h =================================================================== --- tags/1.2.7/src/conf_core.h (nonexistent) +++ tags/1.2.7/src/conf_core.h (revision 13657) @@ -0,0 +1,231 @@ +#ifndef PCB_CONF_CORE_H +#define PCB_CONF_CORE_H + +#include "conf.h" +#include "globalconst.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 */ + } temp; + + const struct editor { + CFT_UNIT grid_unit; /* select whether you draw in mm or mil */ + CFT_COORD grid; /* grid in pcb-units */ + CFT_INCREMENTS increments_mm; /* increments (size deltas) when drawing in mil */ + CFT_INCREMENTS increments_mil; /* increments (size deltas) when drawing in mil */ + 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; /* 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 snp 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 show_number; /* pinout shows number */ + CFT_BOOLEAN orthogonal_moves; /* move items orthogonally. */ + CFT_BOOLEAN reset_after_element; /* reset connections after each element while saving all connections */ + CFT_BOOLEAN auto_place; /* flag which says we should force placement of the windows on startup */ + 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 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, element names are not drawn. */ + CFT_BOOLEAN description; /* display element description as element name, instead of value */ + CFT_BOOLEAN name_on_pcb; /* display Reference Designator as element name, instead of value */ + 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_REAL route_radius; /* temporary: route draw helper's arc radius at corners (factor of the trace thickness) */ + + 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 */ + } editor; + + const struct rc { + CFT_INTEGER verbose; + CFT_INTEGER quiet; /* print only errors on stderr */ + CFT_INTEGER backup_interval; /* time between two backups in seconds; 0 means disabled (no backups) */ + 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 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 anonymous .pcb files; optional fields: %P --> pid */ + 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 */ + + /***** 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 max_width; + CFT_COORD max_height; + CFT_COORD alignment_distance;/* default drc size */ + CFT_COORD bloat; /* default drc size */ + CFT_COORD shrink; + CFT_COORD min_wid; + CFT_COORD min_slk; + CFT_COORD min_drill; + CFT_COORD min_ring; + CFT_INTEGER text_scale; /* text scaling in % */ + CFT_INTEGER text_font_id; + CFT_REAL poly_isle_area; /* polygon min area */ + CFT_STRING default_layer_name[PCB_MAX_LAYER]; + CFT_STRING fab_author; /* Full name of author for FAB drawings */ + CFT_STRING initial_layer_stack; /* deprecated. */ + + CFT_STRING groups; /* string with layergroups */ + CFT_STRING routes; /* string with route styles */ + + CFT_COORD paste_adjust; /* Adjust paste thickness */ + } design; + +/* @path appearance/color */ + const struct appearance { + 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 */ + 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 black; + CFT_COLOR white; + CFT_COLOR background; /* background and cursor color ... */ + CFT_COLOR crosshair; /* different object colors */ + CFT_COLOR cross; + CFT_COLOR via; + CFT_COLOR via_selected; + CFT_COLOR pin; + CFT_COLOR pin_selected; + CFT_COLOR pin_name; + CFT_COLOR element; + CFT_COLOR element_nonetlist; + CFT_COLOR subc; + CFT_COLOR subc_selected; + CFT_COLOR subc_nonetlist; + CFT_COLOR padstackmark; /* color of the center mark cross for padstacks */ + CFT_COLOR rat; + CFT_COLOR invisible_objects; + CFT_COLOR invisible_mark; + CFT_COLOR element_selected; + CFT_COLOR rat_selected; + CFT_COLOR connected; + CFT_COLOR off_limit; + CFT_COLOR grid; + CFT_COLOR layer[PCB_MAX_LAYER]; + CFT_COLOR layer_selected[PCB_MAX_LAYER]; + CFT_COLOR warn; + CFT_COLOR mask; + CFT_COLOR paste; + } color; + struct pinout { + CFT_INTEGER name_length; + CFT_REAL zoom; + CFT_COORD offset_x; /* X offset of origin */ + CFT_COORD offset_y; /* Y offset of origin */ + CFT_COORD text_offset_x; /* X offset of text from pin center */ + CFT_COORD text_offset_y; /* Y offset of text from pin center */ + } pinout; + 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/1.2.7/src/conf_hid.c =================================================================== --- tags/1.2.7/src/conf_hid.c (nonexistent) +++ tags/1.2.7/src/conf_hid.c (revision 13657) @@ -0,0 +1,138 @@ +#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 = 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) +{ + 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/1.2.7/src/conf_hid.h =================================================================== --- tags/1.2.7/src/conf_hid.h (nonexistent) +++ tags/1.2.7/src/conf_hid.h (revision 13657) @@ -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/1.2.7/src/const.h =================================================================== --- tags/1.2.7/src/const.h (nonexistent) +++ tags/1.2.7/src/const.h (revision 13657) @@ -0,0 +1,93 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* global source constants */ + +#ifndef PCB_CONST_H +#define PCB_CONST_H + +/* --------------------------------------------------------------------------- + * modes + */ +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; + +/* --------------------------------------------------------------------------- + * object types (bitfield) + */ +typedef enum { + PCB_TYPE_NONE = 0x00000, /* special: no object */ + PCB_TYPE_VIA = 0x00001, + PCB_TYPE_ELEMENT = 0x00002, + PCB_TYPE_LINE = 0x00004, + PCB_TYPE_POLY = 0x00008, + PCB_TYPE_TEXT = 0x00010, + PCB_TYPE_RATLINE = 0x00020, + PCB_TYPE_SUBC = 0x00040, /* TODO: should be 0x00002 once PCB_TYPE_ELEMENT is removed */ + + PCB_TYPE_PIN = 0x00100, /* objects that are part */ + PCB_TYPE_PAD = 0x00200, /* 'pin' of SMD element */ + PCB_TYPE_ELEMENT_NAME = 0x00400, /* of others */ + PCB_TYPE_POLY_POINT = 0x00800, + PCB_TYPE_LINE_POINT = 0x01000, + PCB_TYPE_ELEMENT_LINE = 0x02000, + PCB_TYPE_ARC = 0x04000, + PCB_TYPE_ELEMENT_ARC = 0x08000, + + PCB_TYPE_LOCKED = 0x10000, /* used to tell search to include locked items. */ + PCB_TYPE_SUBC_PART = 0x20000, /* used to tell search to include objects that are part of a subcircuit */ + PCB_TYPE_NET = 0x40000, /* used to select whole net. */ + + PCB_TYPE_ARC_POINT = 0x80000, + PCB_TYPE_PSTK = 0x100000, + + /* groups/properties */ + PCB_TYPEMASK_PIN = (PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_PSTK | PCB_TYPE_SUBC_PART), + PCB_TYPEMASK_TERM = (PCB_TYPEMASK_PIN | PCB_TYPE_SUBC_PART | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_TEXT), + PCB_TYPEMASK_LOCK = (PCB_TYPE_PSTK | PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_LOCKED), + + PCB_TYPEMASK_ALL = (~0) /* all bits set */ +} pcb_obj_type_t; + +#endif Index: tags/1.2.7/src/copy.c =================================================================== --- tags/1.2.7/src/copy.c (nonexistent) +++ tags/1.2.7/src/copy.c (revision 13657) @@ -0,0 +1,75 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* functions used to copy pins, elements ... + * it's necessary to copy data by calling create... since the base pointer + * may change cause of dynamic memory allocation + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "select.h" +#include "undo.h" +#include "obj_all_op.h" +#include "obj_pstk_op.h" + +static pcb_opfunc_t CopyFunctions = { + pcb_lineop_copy, + pcb_textop_copy, + pcb_polyop_copy, + pcb_viaop_copy, + pcb_elemop_copy, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_copy, + NULL, + NULL, + pcb_subcop_copy, + pcb_pstkop_copy +}; + +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/1.2.7/src/copy.h =================================================================== --- tags/1.2.7/src/copy.h (nonexistent) +++ tags/1.2.7/src/copy.h (revision 13657) @@ -0,0 +1,40 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_COPY_H +#define PCB_COPY_H + +#include "config.h" + +#define PCB_COPY_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PSTK | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | \ + PCB_TYPE_SUBC | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_POLY | PCB_TYPE_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/1.2.7/src/crosshair.c =================================================================== --- tags/1.2.7/src/crosshair.c (nonexistent) +++ tags/1.2.7/src/crosshair.c (revision 13657) @@ -0,0 +1,1693 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* crosshair stuff */ + +#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 "hid_actions.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "vtonpoint.h" +#include "find.h" +#include "undo.h" +#include "event.h" +#include "action_helper.h" + +#include "obj_line_draw.h" +#include "obj_arc_draw.h" +#include "obj_text_draw.h" +#include "obj_pstk_draw.h" +#include "obj_arc_ui.h" +#include "obj_all_op.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 XORDrawElement(pcb_element_t *, pcb_coord_t, pcb_coord_t); +static void XORDrawPadDRCOutline(pcb_pad_t * pv,pcb_coord_t clearance); + +static void thindraw_moved_pv(pcb_pin_t * pv, pcb_coord_t x, pcb_coord_t y) +{ + /* Make a copy of the pin structure, moved to the correct position */ + pcb_pin_t moved_pv = *pv; + moved_pv.X += x; + moved_pv.Y += y; + + pcb_gui->thindraw_pcb_pv(pcb_crosshair.GC, pcb_crosshair.GC, &moved_pv, pcb_true, pcb_false); + + if (conf_core.editor.show_drc) { + /* XXX: Naughty cheat - use the mask to draw DRC clearance! */ + moved_pv.Mask = conf_core.design.via_thickness + PCB->Bloat * 2; + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawPinViaDRCOutline(&moved_pv,PCB->Bloat); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } +} + +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(pcb_crosshair.GC, &moved_ps); +} + +/* --------------------------------------------------------------------------- + * creates a tmp polygon with coordinates converted to screen system + */ +void XORPolygon(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(pcb_crosshair.GC, + polygon->Points[i].X + dx, + polygon->Points[i].Y + dy, polygon->Points[next].X + dx, polygon->Points[next].Y + dy); + 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 XORPolygon_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); + } +} + +/*----------------------------------------------------------- + * Draws the outline of an attached arc + */ +void XORDrawAttachedArc(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); +} + +/* --------------------------------------------------------------------------- + * draws the elements of a loaded circuit which is to be merged in + */ +static void XORDrawElement(pcb_element_t *Element, pcb_coord_t DX, pcb_coord_t DY) +{ + /* if no silkscreen, draw the bounding box */ + if (arclist_length(&Element->Arc) == 0 && linelist_length(&Element->Line) == 0) { + pcb_gui->draw_line(pcb_crosshair.GC, + DX + Element->BoundingBox.X1, + DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y2); + pcb_gui->draw_line(pcb_crosshair.GC, + DX + Element->BoundingBox.X1, + DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y2); + pcb_gui->draw_line(pcb_crosshair.GC, + DX + Element->BoundingBox.X2, + DY + Element->BoundingBox.Y2, DX + Element->BoundingBox.X2, DY + Element->BoundingBox.Y1); + pcb_gui->draw_line(pcb_crosshair.GC, + DX + Element->BoundingBox.X2, + DY + Element->BoundingBox.Y1, DX + Element->BoundingBox.X1, DY + Element->BoundingBox.Y1); + } + else { + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_gui->draw_line(pcb_crosshair.GC, DX + line->Point1.X, DY + line->Point1.Y, DX + line->Point2.X, DY + line->Point2.Y); + } + PCB_END_LOOP; + + /* arc coordinates and angles have to be converted to X11 notation */ + PCB_ARC_LOOP(Element); + { + pcb_gui->draw_arc(pcb_crosshair.GC, DX + arc->X, DY + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + } + PCB_END_LOOP; + } + /* pin coordinates and angles have to be converted to X11 notation */ + PCB_PIN_LOOP(Element); + { + thindraw_moved_pv(pin, DX, DY); + } + PCB_END_LOOP; + + /* pads */ + PCB_PAD_LOOP(Element); + { + if (PCB->InvisibleObjectsOn || (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) != 0) == conf_core.editor.show_solder_side) { + /* Make a copy of the pad structure, moved to the correct position */ + pcb_pad_t moved_pad = *pad; + moved_pad.Point1.X += DX; + moved_pad.Point1.Y += DY; + moved_pad.Point2.X += DX; + moved_pad.Point2.Y += DY; + + pcb_gui->thindraw_pcb_pad(pcb_crosshair.GC, &moved_pad, pcb_false, pcb_false); + + /* 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); + XORDrawPadDRCOutline(&moved_pad,PCB->Bloat); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } + } + } + PCB_END_LOOP; + /* mark */ + pcb_gui->draw_line(pcb_crosshair.GC, + Element->MarkX + DX - PCB_EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, + Element->MarkX + DX + PCB_EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, + Element->MarkX + DX - PCB_EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, + Element->MarkX + DX + PCB_EMARK_SIZE, Element->MarkY + DY, Element->MarkX + DX, Element->MarkY + DY + PCB_EMARK_SIZE); +} + +/* --------------------------------------------------------------------------- + * draws all visible and attached objects of the pastebuffer + */ +void XORDrawBuffer(pcb_buffer_t *Buffer) +{ + pcb_cardinal_t i; + pcb_coord_t x, y; + + /* set offset */ + x = pcb_crosshair.X - Buffer->X; + y = pcb_crosshair.Y - 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); + } + 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); + { + XORPolygon(polygon, x, y, 0); + } + PCB_END_LOOP; + } + + /* draw elements if visible */ + if (PCB->PinOn && pcb_silk_on(PCB)) { + PCB_ELEMENT_LOOP(Buffer->Data); + { + if (PCB_FRONT(element) || PCB->InvisibleObjectsOn) + XORDrawElement(element, x, y); + } + PCB_END_LOOP; + } + + /* draw subcircuit */ + PCB_SUBC_LOOP(Buffer->Data); + { + XORDrawSubc(subc, x, y, Buffer->from_outside); + } + PCB_END_LOOP; + + /* and the vias */ + if (PCB->ViaOn) + PCB_VIA_LOOP(Buffer->Data); + { + thindraw_moved_pv(via, x, y); + } + PCB_END_LOOP; + + /* and the padstacks */ + if (PCB->ViaOn) + PCB_PADSTACK_LOOP(Buffer->Data); + { + thindraw_moved_ps(padstack, x, y); + } + PCB_END_LOOP; + +} + +/* --------------------------------------------------------------------------- + * draws the rubberband to insert points into polygons/lines/... + */ +void XORDrawInsertPointObject(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_TYPE_NONE) { + 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 XORDrawMoveOrCopy(void) +{ + pcb_coord_t dx = pcb_crosshair.X - pcb_crosshair.AttachedObject.X; + pcb_coord_t dy = pcb_crosshair.Y - pcb_crosshair.AttachedObject.Y; + int event_sent = 0; + + switch (pcb_crosshair.AttachedObject.Type) { + case PCB_TYPE_VIA: + { + pcb_pin_t *via = (pcb_pin_t *) pcb_crosshair.AttachedObject.Ptr1; + thindraw_moved_pv(via, dx, dy); + break; + } + + case PCB_TYPE_PSTK: + { + pcb_pstk_t *ps = (pcb_pstk_t *) pcb_crosshair.AttachedObject.Ptr1; + thindraw_moved_ps(ps, dx, dy); + break; + } + + case PCB_TYPE_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; + + int dx1 = dx, dx2 = dx; + int 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 * (PCB->Bloat + 1), 0); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } + break; + } + + case PCB_TYPE_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); + + /* 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 * (PCB->Bloat + 1); + pcb_draw_wireframe_arc(pcb_crosshair.GC,&arc); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } + break; + } + + case PCB_TYPE_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 + */ + XORPolygon(polygon, dx, dy, 0); + break; + } + + case PCB_TYPE_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 * (PCB->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_TYPE_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); + + /* 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 * (PCB->Bloat + 1); + pcb_draw_wireframe_arc(pcb_crosshair.GC,&arc); + 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_TYPE_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_TYPE_ELEMENT_NAME: + { + /* locate the element "mark" and draw an association line from crosshair to it */ + pcb_element_t *element = (pcb_element_t *) pcb_crosshair.AttachedObject.Ptr1; + + pcb_gui->draw_line(pcb_crosshair.GC, element->MarkX, element->MarkY, pcb_crosshair.X, pcb_crosshair.Y); + /* fall through to move the text as a box outline */ + } + case PCB_TYPE_TEXT: + { + pcb_text_t *text = (pcb_text_t *) pcb_crosshair.AttachedObject.Ptr2; + pcb_text_draw_xor(text, dx, dy); + break; + } + + /* pin/pad movements result in moving an element */ + case PCB_TYPE_PAD: + case PCB_TYPE_PIN: + case PCB_TYPE_ELEMENT: + XORDrawElement((pcb_element_t *) pcb_crosshair.AttachedObject.Ptr2, dx, dy); + break; + + case PCB_TYPE_SUBC: + XORDrawSubc((pcb_subc_t *) pcb_crosshair.AttachedObject.Ptr2, dx, dy, 0); + break; + } + + /* floaters have a line 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; + 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 the DRC Outline of a pad/via shape with the given style and clearance + */ +static void +draw_pinvia_shape_drc_outline( pcb_hid_gc_t gc, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t clearance, int style) +{ + struct {double X, Y, angle;} p[8] = { + {0.5, -PCB_TAN_22_5_DEGREE_2, 180.0}, + {PCB_TAN_22_5_DEGREE_2, -0.5, 270.0}, + {-PCB_TAN_22_5_DEGREE_2, -0.5, 270.0 }, + {-0.5, -PCB_TAN_22_5_DEGREE_2, 0.0}, + {-0.5, PCB_TAN_22_5_DEGREE_2, 0.0}, + {-PCB_TAN_22_5_DEGREE_2, 0.5, 90.0}, + {PCB_TAN_22_5_DEGREE_2, 0.5, 90.0}, + {0.5, PCB_TAN_22_5_DEGREE_2, 180.0} + }; + + pcb_coord_t polygon_x[9]; + pcb_coord_t polygon_y[9]; + double xm[8]; + double ym[8]; + double xn[8]; + double yn[8]; + double a[8]; + int i; + const double factor = 2.0; + + /* Constants for Normals and Arc Angles */ + const double N0 = 0.7071067; + const double N1 = 0.44721279658; + const double N2 = 0.89442759; + const double A0 = 45.0; + const double A1 = 26.565; + const double A2 = 63.435; + + style = (style-1) & 0x0F; + + /* Calculate multipliers*/ + for (i = 0; i < 8; i++) { + xm[i] = 1; + ym[i] = 1; + } + + if (style & 1) + xm[0] = xm[1] = xm[6] = xm[7] = factor; + if (style & 2) + xm[2] = xm[3] = xm[4] = xm[5] = factor; + if (style & 4) + ym[4] = ym[5] = ym[6] = ym[7] = factor; + if (style & 8) + ym[0] = ym[1] = ym[2] = ym[3] = factor; + + /* Select Edge Normals and Arc Angles */ + xn[1] = xn[5] = 0.0; + yn[3] = yn[7] = 0.0; + yn[1] = -1.0; + yn[5] = 1.0; + xn[3] = -1.0; + xn[7] = +1.0; + + switch(style & 9) { + case 1 : xn[0] = N1; yn[0] = -N2; a[0] = A2; a[1] = -A1; break; + case 8 : xn[0] = N2; yn[0] = -N1; a[0] = A1; a[1] = -A2; break; + default : xn[0] = N0; yn[0] = -N0; a[0] = A0; a[1] = -A0; break; + } + + switch(style & 10) { + case 2 : xn[2] = -N1; yn[2] = -N2; a[2] = A1; a[3] = -A2; break; + case 8 : xn[2] = -N2; yn[2] = -N1; a[2] = A2; a[3] = -A1; break; + default : xn[2] = -N0; yn[2] = -N0; a[2] = A0; a[3] = -A0; break; + } + + switch(style & 5) { + case 1 : xn[6] = N1; yn[6] = N2; a[6] = A1; a[7] = -A2; break; + case 4 : xn[6] = N2; yn[6] = N1; a[6] = A2; a[7] = -A1; break; + default : xn[6] = N0; yn[6] = N0; a[6] = A0; a[7] = -A0; break; + } + + switch(style & 6) { + case 2 : xn[4] = -N1; yn[4] = N2; a[4] = A2; a[5] = -A1; break; + case 4 : xn[4] = -N2; yn[4] = N1; a[4] = A1; a[5] = -A2; break; + default : xn[4] = -N0; yn[4] = N0; a[4] = A0; a[5] = -A0; break; + } + + /* add line offset */ + for (i = 0; i < 8; i++) { + polygon_x[i] = X + (p[i].X * Thickness) * xm[i]; + polygon_y[i] = Y + (p[i].Y * Thickness) * ym[i]; + } + polygon_x[8] = polygon_x[0]; + polygon_y[8] = polygon_y[0]; + + pcb_gui->set_line_cap(gc, Round_Cap); + pcb_gui->set_line_width(gc, 0); + + /* Draw the outline */ + for (i = 0; i < 8; i++) { + pcb_gui->draw_line( gc, + polygon_x[i] + (xn[i] * clearance), + polygon_y[i] + (yn[i] * clearance), + polygon_x[i+1] + (xn[i] * clearance), + polygon_y[i+1] + (yn[i] * clearance) ); + + pcb_gui->draw_arc( gc,polygon_x[i],polygon_y[i],clearance,clearance,p[i].angle,a[i]); + } +} + +/* --------------------------------------------------------------------------- + * draws the DRC Outline of a pin/via with the given clearance + */ +void +XORDrawPinViaDRCOutline(pcb_pin_t * pv,pcb_coord_t clearance) +{ + int style = PCB_FLAG_SQUARE_GET(pv); + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv) || (clearance == 0)) + return; + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pv)) { + if((style==0) || (style==1)) { + pcb_coord_t w = pv->Thickness; + pcb_coord_t l = pv->X - (w/2); + pcb_coord_t b = pv->Y - (w/2); + pcb_coord_t r = l + w; + pcb_coord_t t = b + w; + pcb_coord_t lc = l - clearance; + pcb_coord_t bc = b - clearance; + pcb_coord_t rc = r + clearance; + pcb_coord_t tc = t + clearance; + + pcb_gui->set_line_cap(pcb_crosshair.GC, Round_Cap); + pcb_gui->set_line_width(pcb_crosshair.GC, 0); + pcb_gui->draw_line(pcb_crosshair.GC, rc, t, rc, b); + pcb_gui->draw_line(pcb_crosshair.GC, lc, t, lc, b); + pcb_gui->draw_line(pcb_crosshair.GC, r, tc, l, tc); + pcb_gui->draw_line(pcb_crosshair.GC, r, bc, l, bc); + pcb_gui->draw_arc(pcb_crosshair.GC, r,b,clearance,clearance,180,90); + pcb_gui->draw_arc(pcb_crosshair.GC, r,t,clearance,clearance,90,90); + pcb_gui->draw_arc(pcb_crosshair.GC, l,b,clearance,clearance,270,90); + pcb_gui->draw_arc(pcb_crosshair.GC, l,t,clearance,clearance,0,90); + } + else + draw_pinvia_shape_drc_outline(pcb_crosshair.GC,pv->X,pv->Y,pv->Thickness,clearance,style); + } + else if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pv)) + draw_pinvia_shape_drc_outline(pcb_crosshair.GC,pv->X,pv->Y,pv->Thickness,clearance,17); + else { + pcb_coord_t r = (pv->Thickness/2)+clearance; + + pcb_gui->set_line_cap(pcb_crosshair.GC, Round_Cap); + pcb_gui->set_line_width(pcb_crosshair.GC, 0); + pcb_gui->draw_arc(pcb_crosshair.GC, pv->X, pv->Y, r, r, 0, 360); + } +} + +/* --------------------------------------------------------------------------- + * draws the DRC Outline of a pad with the given clearance + */ +static void +XORDrawPadDRCOutline(pcb_pad_t * pad,pcb_coord_t clearance) +{ + pcb_coord_t x1, y1, x2, y2; + pcb_coord_t t = (pad->Thickness / 2); + x1 = pad->Point1.X; + y1 = pad->Point1.Y; + x2 = pad->Point2.X; + y2 = pad->Point2.Y; + + pcb_gui->set_line_cap(pcb_crosshair.GC, Round_Cap); + pcb_gui->set_line_width(pcb_crosshair.GC, 0); + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad)) { + /* slanted square pad */ + double tx, ty, nx, ny, theta, angle; + pcb_coord_t cx0, cx1, cx2, cx3; + pcb_coord_t cy0, cy1, cy2, cy3; + + if ((x1 == x2) && (y1 == y2)) + theta = 0; + else + theta = atan2(y2 - y1, x2 - x1); + + angle = (270-(theta * PCB_RAD_TO_DEG)); + + /* T is a vector half a thickness long, in the direction of + one of the corners. */ + tx = t * cos(theta + M_PI / 4) * PCB_SQRT2; + ty = t * sin(theta + M_PI / 4) * PCB_SQRT2; + + /* The normal of one of the edges with length = clearance */ + nx = cos(theta + M_PI / 2) * clearance; + ny = sin(theta + M_PI / 2) * clearance; + + /* Coordinates of the pad corners */ + cx0 = x1 - tx; cx1 = x2 + ty; cx2 = x2 + tx; cx3 = x1 - ty; + cy0 = y1 - ty; cy1 = y2 - tx; cy2 = y2 + ty; cy3 = y1 + tx; + + /* Draw the DRC outline*/ + pcb_gui->draw_line(pcb_crosshair.GC, cx0 - nx, cy0 - ny, cx1 - nx, cy1 - ny ); + pcb_gui->draw_line(pcb_crosshair.GC, cx2 + nx, cy2 + ny, cx3 + nx, cy3 + ny ); + pcb_gui->draw_line(pcb_crosshair.GC, cx0 - ny, cy0 + nx, cx3 - ny, cy3 + nx ); + pcb_gui->draw_line(pcb_crosshair.GC, cx1 + ny, cy1 - nx, cx2 + ny, cy2 - nx ); + + pcb_gui->draw_arc(pcb_crosshair.GC,cx0,cy0,clearance,clearance,angle,90); + pcb_gui->draw_arc(pcb_crosshair.GC,cx1,cy1,clearance,clearance,angle-90,90); + pcb_gui->draw_arc(pcb_crosshair.GC,cx2,cy2,clearance,clearance,angle-180,90); + pcb_gui->draw_arc(pcb_crosshair.GC,cx3,cy3,clearance,clearance,angle-270,90); + } + else if (x1 == x2 && y1 == y2) { + pcb_gui->draw_arc(pcb_crosshair.GC, x1, y1, t + clearance, t + clearance, 0, 360); + } + else { + /* Slanted round-end pads. */ + pcb_coord_t dx, dy, ox, oy; + double h; + + t += clearance; + dx = x2 - x1; + dy = y2 - y1; + h = t / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + ox = dy * h + 0.5 * SGN(dy); + oy = -(dx * h + 0.5 * SGN(dx)); + + pcb_gui->draw_line(pcb_crosshair.GC, x1 + ox, y1 + oy, x2 + ox, y2 + oy); + + if (labs(ox) >= pcb_pixel_slop || coord_abs(oy) >= pcb_pixel_slop) { + pcb_angle_t angle = atan2(dx, dy) * 57.295779; + pcb_gui->draw_line(pcb_crosshair.GC, x1 - ox, y1 - oy, x2 - ox, y2 - oy); + pcb_gui->draw_arc(pcb_crosshair.GC, x1, y1, t, t, angle - 180, 180); + pcb_gui->draw_arc(pcb_crosshair.GC, x2, y2, t, t, angle, 180); + } + } +} + +/* --------------------------------------------------------------------------- + * draws additional stuff that follows the crosshair + */ +void pcb_draw_attached(void) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, NULL); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 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); + } + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, NULL); +} + + +/* -------------------------------------------------------------------------- + * draw the marker position + */ +void pcb_draw_mark(void) +{ + pcb_coord_t ms = conf_core.appearance.mark_size; + + /* Mark is not drawn when it is not set */ + if (!pcb_marked.status) + return; + + 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); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, NULL); +} + +/* --------------------------------------------------------------------------- + * Returns the nearest grid-point to the given Coord + */ +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; +} + + +/* --------------------------------------------------------------------------- + * 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_TYPE_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_TYPE_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_TYPE_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_TYPE_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(); + } +} + +/* --------------------------------------------------------------------------- + * Returns the square of the given number + */ +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) +{ + double sq_dist; + + 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_TYPE_LINE, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_TYPE_NONE) + return; + + line = (pcb_line_t *) ptr2; + + /* 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 != ptr1) && + (conf_core.editor.mode != PCB_MODE_MOVE || + pcb_crosshair.AttachedObject.Ptr1 != ptr1 || + pcb_crosshair.AttachedObject.Type != PCB_TYPE_LINE_POINT + || pcb_crosshair.AttachedObject.Ptr2 == 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); + } + + /* 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); + } + + 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); + } + + 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); + } +} + +/* --------------------------------------------------------------------------- + * 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_TYPE_NONE; + if (!PCB->RatDraw) { + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_ELEMENT, &ptr1, &ptr2, &ptr3); + if (ans == 0) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_SUBC, &ptr1, &ptr2, &ptr3); + } + + if (ans & PCB_TYPE_ELEMENT) { + pcb_element_t *el = (pcb_element_t *) ptr1; + check_snap_object(&snap_data, el->MarkX, el->MarkY, pcb_false); + } + + if (ans & PCB_TYPE_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); + } + + ans = PCB_TYPE_NONE; + if (PCB->RatDraw || conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_PAD, &ptr1, &ptr2, &ptr3); + + /* Avoid self-snapping when moving */ + if (ans != PCB_TYPE_NONE && + conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_ELEMENT && ptr1 == pcb_crosshair.AttachedObject.Ptr1) + ans = PCB_TYPE_NONE; + + if (ans != PCB_TYPE_NONE && + (conf_core.editor.mode == PCB_MODE_LINE || (conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_LINE_POINT))) { + pcb_pad_t *pad = (pcb_pad_t *) ptr2; + pcb_layer_t *desired_layer; + pcb_layergrp_id_t desired_group; + pcb_layergrp_id_t SLayer, CLayer; + int found_our_layer = pcb_false; + + desired_layer = CURRENT; + if (conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_LINE_POINT) { + desired_layer = (pcb_layer_t *) pcb_crosshair.AttachedObject.Ptr1; + } + + /* find layer groups of the component side and solder side */ + SLayer = CLayer = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &SLayer, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &CLayer, 1); + desired_group = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? SLayer : CLayer; + + if (desired_group >= 0) { + PCB_COPPER_GROUP_LOOP(PCB->Data, desired_group); + { + if (layer == desired_layer) { + found_our_layer = pcb_true; + break; + } + } + PCB_END_LOOP; + } + + if (found_our_layer == pcb_false) + ans = PCB_TYPE_NONE; + } + + if (ans != PCB_TYPE_NONE) { + pcb_pad_t *pad = (pcb_pad_t *) ptr2; + check_snap_object(&snap_data, (pad->Point1.X + pad->Point2.X) / 2, (pad->Point1.Y + pad->Point2.Y) / 2, pcb_true); + pcb_crosshair.snapped_pad = pad; + } else { + pcb_crosshair.snapped_pad = 0; + } + + ans = PCB_TYPE_NONE; + if (PCB->RatDraw || conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_PIN, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_TYPE_NONE) + if (PCB->RatDraw || conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_VIA | PCB_TYPE_SUBC_PART, &ptr1, &ptr2, &ptr3); + + /* Avoid self-snapping when moving */ + /* SUBC/TERM note: this behavior is wrong, let the user use shift to verride */ + if (ans != PCB_TYPE_NONE && + conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_ELEMENT && ptr1 == pcb_crosshair.AttachedObject.Ptr1) + ans = PCB_TYPE_NONE; + + if (ans != PCB_TYPE_NONE) { + pcb_pin_t *pin = (pcb_pin_t *) ptr2; + check_snap_object(&snap_data, pin->X, pin->Y, pcb_true); + pcb_crosshair.snapped_pin = pin; + } else { + pcb_crosshair.snapped_pin = 0; + } + + ans = PCB_TYPE_NONE; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_VIA, &ptr1, &ptr2, &ptr3); + + /* Avoid snapping vias to any other vias */ + if (conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_VIA && (ans & PCB_TYPEMASK_PIN)) + ans = PCB_TYPE_NONE; + + if (ans != PCB_TYPE_NONE) { + pcb_pin_t *pin = (pcb_pin_t *) ptr2; + check_snap_object(&snap_data, pin->X, pin->Y, pcb_true); + pcb_crosshair.snapped_pin = pin; + } + + /*** padstack center ***/ + ans = PCB_TYPE_NONE; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_PSTK | PCB_TYPE_SUBC_PART, &ptr1, &ptr2, &ptr3); + + /* Avoid snapping padstack to any other vias */ + if (conf_core.editor.mode == PCB_MODE_MOVE && pcb_crosshair.AttachedObject.Type == PCB_TYPE_VIA && (ans & PCB_TYPEMASK_PIN)) + ans = PCB_TYPE_NONE; + + if (ans != PCB_TYPE_NONE) { + pcb_pstk_t *ps = (pcb_pstk_t *) ptr2; + check_snap_object(&snap_data, ps->x, ps->y, pcb_true); + pcb_crosshair.snapped_pstk = ps; + } + + /*** arc ***/ + ans = PCB_TYPE_NONE; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_LINE_POINT | PCB_TYPE_ARC_POINT | PCB_TYPE_SUBC_PART, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_TYPE_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); + } + else if (ans != PCB_TYPE_NONE) { + pcb_point_t *pnt = (pcb_point_t *) ptr3; + check_snap_object(&snap_data, pnt->X, pnt->Y, pcb_true); + } + + /*** polygon terminal: center ***/ + ans = PCB_TYPE_NONE; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_POLY | PCB_TYPE_SUBC_PART, &ptr1, &ptr2, &ptr3); + + if (ans == PCB_TYPE_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); + } + } + + /* + * 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_TYPE_NONE; + if (conf_core.editor.snap_pin) + ans = pcb_search_grid_slop(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_POLY_POINT, &ptr1, &ptr2, &ptr3); + + if (ans != PCB_TYPE_NONE) { + pcb_point_t *pnt = (pcb_point_t *) ptr3; + check_snap_object(&snap_data, pnt->X, pnt->Y, pcb_true); + } + + 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_TYPE_LINE_POINT, &ptr1, &ptr2, &ptr3); + if (ans == PCB_TYPE_NONE) { + 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; + 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); +} + +/* --------------------------------------------------------------------------- + * sets the valid range for the crosshair cursor + */ +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_gui->make_gc(); + + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + pcb_gui->set_draw_xor(pcb_crosshair.GC, 1); + pcb_gui->set_line_cap(pcb_crosshair.GC, Trace_Cap); + pcb_gui->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); + +} + +/* --------------------------------------------------------------------------- + * exits crosshair routines, release GCs + */ +void pcb_crosshair_uninit(void) +{ + pcb_poly_free_fields(&pcb_crosshair.AttachedPolygon); + pcb_route_destroy(&pcb_crosshair.Route); + pcb_gui->destroy_gc(pcb_crosshair.GC); +} + +/************************* mode *************************************/ +static int mode_position = 0; +static int mode_stack[PCB_MAX_MODESTACK_DEPTH]; + +/* sets the crosshair range to the current buffer extents */ +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->BoundingBox.X1, + PCB_PASTEBUFFER->Y - PCB_PASTEBUFFER->BoundingBox.Y1, + PCB->MaxWidth - + (PCB_PASTEBUFFER->BoundingBox.X2 - PCB_PASTEBUFFER->X), + PCB->MaxHeight - (PCB_PASTEBUFFER->BoundingBox.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_save_mode(void) +{ + mode_stack[mode_position] = conf_core.editor.mode; + if (mode_position < PCB_MAX_MODESTACK_DEPTH - 1) + mode_position++; +} + +void pcb_crosshair_restore_mode(void) +{ + if (mode_position == 0) { + pcb_message(PCB_MSG_ERROR, "hace: underflow of restore mode\n"); + return; + } + pcb_crosshair_set_mode(mode_stack[--mode_position]); +} + + +/* set a new mode and update X cursor */ +void pcb_crosshair_set_mode(int Mode) +{ + char sMode[32]; + static pcb_bool recursing = pcb_false; + /* protect the cursor while changing the mode + * perform some additional stuff depending on the new mode + * reset 'state' of attached objects + */ + if (recursing) + return; + recursing = pcb_true; + pcb_notify_crosshair_change(pcb_false); + pcb_added_lines = 0; + pcb_route_reset(&pcb_crosshair.Route); + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedPolygon.PointN = 0; + if (PCB->RatDraw) { + if (Mode == PCB_MODE_ARC || Mode == PCB_MODE_RECTANGLE || + Mode == PCB_MODE_VIA || Mode == PCB_MODE_POLYGON || + Mode == PCB_MODE_POLYGON_HOLE || Mode == PCB_MODE_TEXT || Mode == PCB_MODE_THERMAL) { + pcb_message(PCB_MSG_WARNING, _("That mode is NOT allowed when drawing ratlines!\n")); + Mode = PCB_MODE_NO; + } + } + if (conf_core.editor.mode == PCB_MODE_LINE && Mode == PCB_MODE_ARC && 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_adjust_attached_objects(); + } + else if (conf_core.editor.mode == PCB_MODE_ARC && Mode == PCB_MODE_LINE && 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; + sprintf(sMode, "%d", Mode); + conf_set(CFR_DESIGN, "editor/mode", -1, sMode, POL_OVERWRITE); + pcb_adjust_attached_objects(); + } + else { + if (conf_core.editor.mode == PCB_MODE_ARC || conf_core.editor.mode == PCB_MODE_LINE) + pcb_crosshair_set_local_ref(0, 0, pcb_false); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + if (Mode == PCB_MODE_LINE && conf_core.editor.auto_drc) { + if (pcb_reset_conns(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + } + } + + sprintf(sMode, "%d", Mode); + conf_set(CFR_DESIGN, "editor/mode", -1, sMode, POL_OVERWRITE); + + if (Mode == PCB_MODE_PASTE_BUFFER) + /* do an update on the crosshair range */ + pcb_crosshair_range_to_buffer(); + else + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); + + recursing = pcb_false; + + /* force a crosshair grid update because the valid range + * may have changed + */ + pcb_crosshair_move_relative(0, 0); + pcb_notify_crosshair_change(pcb_true); +} + +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); + } +} + Index: tags/1.2.7/src/crosshair.h =================================================================== --- tags/1.2.7/src/crosshair.h (nonexistent) +++ tags/1.2.7/src/crosshair.h (revision 13657) @@ -0,0 +1,141 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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, /* start- and end-position */ + Point2; + 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_box_t BoundingBox; + long int Type, /* object type */ + State; + void *Ptr1, /* three pointers to data, see */ + *Ptr2, /* search.c */ + *Ptr3; + 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 cursor information */ + pcb_hid_gc_t GC, /* GC for cursor drawing */ + AttachGC; /* and for displaying buffer contents */ + pcb_coord_t X, Y, /* position in PCB coordinates */ + MinX, MinY, /* lowest and highest coordinates */ + MaxX, MaxY; + 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_pad_t *snapped_pad; + pcb_pin_t *snapped_pin; + 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 */ +} 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; + + +pcb_coord_t pcb_grid_fit(pcb_coord_t x, pcb_coord_t grid_spacing, pcb_coord_t grid_offset); +void pcb_notify_crosshair_change(pcb_bool changes_complete); +void pcb_notify_mark_change(pcb_bool changes_complete); +void pcb_draw_attached(void); +void pcb_draw_mark(void); +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); + +/*** cursor/crosshair mode ***/ + +/* sets the crosshair range to the current buffer extents */ +void pcb_crosshair_range_to_buffer(void); +void pcb_crosshair_save_mode(void); +void pcb_crosshair_restore_mode(void); +void pcb_crosshair_set_mode(int Mode); +void pcb_crosshair_set_local_ref(pcb_coord_t X, pcb_coord_t Y, pcb_bool Showing); + + +/*** utility for plugins ***/ +void XORDrawAttachedLine(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t); +void XORPolygon(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, int dash_last); +void XORPolygon_subc(pcb_poly_t *polygon, pcb_coord_t dx, pcb_coord_t dy, pcb_coord_t w, pcb_coord_t h, int mirr); +void XORDrawPinViaDRCOutline(pcb_pin_t * pv,pcb_coord_t clearance); +void XORDrawAttachedArc(pcb_coord_t thick); +void XORDrawBuffer(pcb_buffer_t *Buffer); +void XORDrawMoveOrCopy(void); +void XORDrawInsertPointObject(void); + + + +#endif Index: tags/1.2.7/src/data.c =================================================================== --- tags/1.2.7/src/data.c (nonexistent) +++ tags/1.2.7/src/data.c (revision 13657) @@ -0,0 +1,665 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* just defines common identifiers + */ +#include "config.h" + +#include "board.h" +#include "data.h" +#include "data_list.h" +#include "rtree.h" +#include "list_common.h" +#include "obj_all.h" +#include "layer_it.h" +#include "operation.h" + +/* --------------------------------------------------------------------------- + * some shared identifiers + */ +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; + + +/* 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)) { + 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; + if (lacb != NULL) + if (lacb(ctx, pcb, layer, 1)) + continue; + 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); + } + } +} + +void pcb_loop_subc(pcb_board_t *pcb, void *ctx, pcb_subc_cb_t scb) +{ + if (scb != NULL) { + PCB_SUBC_LOOP(pcb->Data); + { + scb(ctx, pcb, subc, 1); + } + PCB_END_LOOP; + } +} + + +void pcb_loop_elements(pcb_board_t *pcb, void *ctx, pcb_element_cb_t ecb, pcb_eline_cb_t elcb, pcb_earc_cb_t eacb, pcb_etext_cb_t etcb, pcb_epin_cb_t epicb, pcb_epad_cb_t epacb) +{ + if ((ecb != NULL) || (elcb != NULL) || (eacb != NULL) || (etcb != NULL) || (epicb != NULL) || (epacb != NULL)) { + PCB_ELEMENT_LOOP(pcb->Data); + { + if (ecb != NULL) + if (ecb(ctx, pcb, element, 1)) + continue; + + if (elcb != NULL) { + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + elcb(ctx, pcb, element, line); + } + PCB_END_LOOP; + } + + if (eacb != NULL) { + PCB_ELEMENT_ARC_LOOP(element); + { + eacb(ctx, pcb, element, arc); + } + PCB_END_LOOP; + } + + if (etcb != NULL) { + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + etcb(ctx, pcb, element, text); + } + PCB_END_LOOP; + } + + if (epicb != NULL) { + PCB_PIN_LOOP(element); + { + epicb(ctx, pcb, element, pin); + } + PCB_END_LOOP; + } + + + if (epacb != NULL) { + PCB_PAD_LOOP(element); + { + epacb(ctx, pcb, element, pad); + } + PCB_END_LOOP; + } + + if (ecb != NULL) + ecb(ctx, pcb, element, 0); + } + PCB_END_LOOP; + } +} + +void pcb_loop_vias(pcb_board_t *pcb, void *ctx, pcb_via_cb_t vcb) +{ + if (vcb != NULL) { + PCB_VIA_LOOP(pcb->Data); + { + vcb(ctx, pcb, via); + } + 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->Data); + { + 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_element_cb_t ecb, pcb_eline_cb_t elcb, pcb_earc_cb_t eacb, pcb_etext_cb_t etcb, pcb_epin_cb_t epicb, pcb_epad_cb_t epacb, + pcb_subc_cb_t scb, + pcb_via_cb_t vcb, pcb_pstk_cb_t pscb + ) +{ + pcb_loop_layers(pcb, ctx, lacb, lcb, acb, tcb, pocb); + pcb_loop_elements(pcb, ctx, ecb, elcb, eacb, etcb, epicb, epacb); + pcb_loop_subc(pcb, ctx, scb); + pcb_loop_vias(pcb, ctx, vcb); + pcb_loop_pstk(pcb, ctx, pscb); +} + +/* --------------------------------------------------------------------------- + * free memory used by data struct + */ +void pcb_data_free(pcb_data_t * data) +{ + pcb_layer_t *layer; + int i, subc; + + if (data == NULL) + return; + + subc = (data->parent_type == PCB_PARENT_SUBC); + + + PCB_VIA_LOOP(data); + { + free(via->Name); + } + PCB_END_LOOP; + list_map0(&data->Via, pcb_pin_t, pcb_via_free); + PCB_ELEMENT_LOOP(data); + { + pcb_element_destroy(element); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(data); + { + pcb_subc_free(subc); + } + PCB_END_LOOP; + + list_map0(&data->Element, pcb_element_t, pcb_element_free); + list_map0(&data->Rat, pcb_rat_t, pcb_rat_free); + + for (layer = data->Layer, i = 0; i < data->LayerN; layer++, i++) { + if (!layer->is_bound) + pcb_attribute_free(&layer->meta.real.Attributes); + PCB_TEXT_LOOP(layer); + { + free(text->TextString); + } + PCB_END_LOOP; + PCB_LINE_LOOP(layer); + { + if (line->Number) + free(line->Number); + } + 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); + } + } + + if (!subc) { + if (data->element_tree) + pcb_r_destroy_tree(&data->element_tree); + if (data->subc_tree) + pcb_r_destroy_tree(&data->subc_tree); + for (i = 0; i < PCB_MAX_ELEMENTNAMES; i++) + if (data->name_tree[i]) + pcb_r_destroy_tree(&data->name_tree[i]); + if (data->via_tree) + pcb_r_destroy_tree(&data->via_tree); + if (data->pin_tree) + pcb_r_destroy_tree(&data->pin_tree); + if (data->pad_tree) + pcb_r_destroy_tree(&data->pad_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); + + /* clear struct */ + memset(data, 0, sizeof(pcb_data_t)); +} + +/* --------------------------------------------------------------------------- + * returns pcb_true if data area is empty + */ +pcb_bool pcb_data_is_empty(pcb_data_t *Data) +{ + pcb_bool hasNoObjects; + pcb_cardinal_t i; + + hasNoObjects = (pinlist_length(&Data->Via) == 0); + hasNoObjects &= (elementlist_length(&Data->Element) == 0); + for (i = 0; i < Data->LayerN; i++) + hasNoObjects = hasNoObjects && pcb_layer_is_empty_(PCB, &(Data->Layer[i])); + return (hasNoObjects); +} + +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_VIA_LOOP(Data); + { + pcb_pin_bbox(via); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, via)) + pcb_box_bump_box(out, &via->BoundingBox); + } + PCB_END_LOOP; + 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_ELEMENT_LOOP(Data); + { + pcb_element_bbox(Data, element, pcb_font(PCB, 0, 0)); + if (!ignore_floaters || !PCB_FLAG_TEST(PCB_FLAG_FLOATER, element)) + pcb_box_bump_box(out, &element->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); +} + +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; +} + +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->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); + pcb_layer_real2bound_offs(&data->Layer[n], pcb4layer_groups, &data->Layer[n]); + data->Layer[n].parent = data; + data->Layer[n].meta.bound.type = lyt; + } +} + +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; + } +} + +pcb_data_t *pcb_data_new(pcb_board_t *parent) +{ + pcb_data_t *data; + data = (pcb_data_t *) calloc(1, sizeof(pcb_data_t)); + 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_bool text_too, pcb_bool pstk_smirror) +{ + PCB_VIA_LOOP(data); + { + pcb_via_mirror(data, via, y_offs); + } + PCB_END_LOOP; + PCB_PADSTACK_LOOP(data); + { + pcb_pstk_mirror(padstack, y_offs, pstk_smirror); + } + 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; + + if (text_too) { + PCB_TEXT_ALL_LOOP(data); + { + pcb_text_flip_side(layer, text, y_offs); + } + 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); +} + + +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_VIA_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_VIA, via, via, via); + } + PCB_END_LOOP; + PCB_ELEMENT_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_ELEMENT, element, element, element); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_SUBC, subc, subc, subc); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_LINE, layer, line, line); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_ARC, layer, arc, arc); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_TEXT, layer, text, text); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(data); + { + pcb_object_operation(&MoveFunctions, &ctx, PCB_TYPE_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_VIA) PCB_VIA_LOOP(data); { + if (PCB_FLAG_TEST(mask, via)) vtp0_append(dst, via); + } PCB_END_LOOP; + if (type & PCB_OBJ_ELEMENT) PCB_ELEMENT_LOOP(data); { + if (PCB_FLAG_TEST(mask, element)) vtp0_append(dst, element); + } PCB_END_LOOP; + if (type & PCB_OBJ_SUBC) PCB_SUBC_LOOP(data); { + if (PCB_FLAG_TEST(mask, subc)) vtp0_append(dst, subc); + } PCB_END_LOOP; + if (type & PCB_OBJ_LINE) PCB_LINE_ALL_LOOP(data); { + if (PCB_FLAG_TEST(mask, line)) vtp0_append(dst, line); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_ARC) PCB_ARC_ALL_LOOP(data); { + if (PCB_FLAG_TEST(mask, arc)) vtp0_append(dst, arc); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_TEXT) PCB_TEXT_ALL_LOOP(data); { + if (PCB_FLAG_TEST(mask, text)) vtp0_append(dst, text); + } PCB_ENDALL_LOOP; + if (type & PCB_OBJ_POLY) PCB_POLY_ALL_LOOP(data); { + if (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) +{ + if (type & PCB_OBJ_VIA) PCB_VIA_LOOP(data); { + if (via->term != NULL) vtp0_append(dst, via); + } PCB_END_LOOP; +#warning TODO: subc TODO +/* 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_layer_id_t lid; + pcb_r_dir_t res = 0; + + if (types & PCB_OBJ_VIA) rsearch(data->via_tree); + if (types & PCB_OBJ_RAT) rsearch(data->rat_tree); + if (types & PCB_OBJ_PIN) rsearch(data->pin_tree); + if (types & PCB_OBJ_PAD) rsearch(data->pad_tree); + if (types & PCB_OBJ_PSTK) rsearch(data->padstack_tree); + if (types & PCB_OBJ_SUBC) rsearch(data->subc_tree); + + + for(lid = 0; lid < data->LayerN; lid++) { + pcb_layer_t *ly = data->Layer + lid; + 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); + } + + /* safe to remove this block with elements */ + { + int n; + + if (types & PCB_OBJ_ELEMENT) rsearch(data->element_tree); + if (types & PCB_OBJ_ETEXT) + for(n = 0; n < 3; n++) + rsearch(data->name_tree[n]); + } + + return res; +} + + + Index: tags/1.2.7/src/data.h =================================================================== --- tags/1.2.7/src/data.h (nonexistent) +++ tags/1.2.7/src/data.h (revision 13657) @@ -0,0 +1,178 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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_subc_list.h" +#include "vtpadstack.h" + +#include "obj_all_list.h" + +/* 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 { + int LayerN; /* number of layers in this board */ + + pcb_vtpadstack_proto_t ps_protos; + + padstacklist_t padstack; + pinlist_t Via; + pcb_subclist_t subc; + elementlist_t Element; +/**/ + pcb_rtree_t *via_tree, *padstack_tree, *subc_tree, *rat_tree; + pcb_rtree_t *element_tree, *pin_tree, *pad_tree, *name_tree[3]; /* old element support */ + 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; +}; + +#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); + +/* element callbacks */ +typedef int (*pcb_element_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, int enter); +typedef void (*pcb_eline_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, pcb_line_t *line); +typedef void (*pcb_earc_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, pcb_arc_t *arc); +typedef void (*pcb_etext_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, pcb_text_t *text); +typedef void (*pcb_epin_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, pcb_pin_t *pin); +typedef void (*pcb_epad_cb_t)(void *ctx, pcb_board_t *pcb, pcb_element_t *element, pcb_pad_t *pad); + +/* 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_via_cb_t)(void *ctx, pcb_board_t *pcb, pcb_pin_t *via); +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 elements and element primitives. Element is the outer loop. */ +void pcb_loop_elements(pcb_board_t *pcb, void *ctx, pcb_element_cb_t ecb, pcb_eline_cb_t elcb, pcb_earc_cb_t eacb, pcb_etext_cb_t etcb, pcb_epin_cb_t epicb, pcb_epad_cb_t epacb); + +/* Loop over all subcircuits. */ +void pcb_loop_subc(pcb_board_t *pcb, void *ctx, pcb_subc_cb_t scb); + +/* Loop over all vias. */ +void pcb_loop_vias(pcb_board_t *pcb, void *ctx, pcb_via_cb_t vcb); + +/* 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_element_cb_t ecb, pcb_eline_cb_t elcb, pcb_earc_cb_t eacb, pcb_etext_cb_t etcb, pcb_epin_cb_t epicb, pcb_epad_cb_t epacb, + pcb_subc_cb_t scb, + pcb_via_cb_t vcb, pcb_pstk_cb_t pscb +); + +pcb_data_t *pcb_data_new(pcb_board_t *parent); +void pcb_data_free(pcb_data_t *); +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); + +/* 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); + +/* 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); + + +void pcb_data_mirror(pcb_data_t *data, pcb_coord_t y_offs, pcb_bool text_too, pcb_bool pstk_smirror); + +void pcb_data_move(pcb_data_t *data, pcb_coord_t dx, pcb_coord_t dy); + +/* 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); + +#endif Index: tags/1.2.7/src/data_it.h =================================================================== --- tags/1.2.7/src/data_it.h (nonexistent) +++ tags/1.2.7/src/data_it.h (revision 13657) @@ -0,0 +1,140 @@ +/* + * 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. + * + */ + +/* 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_obj_type_t mask; /* caller wants to see these types */ + + /* current state */ + pcb_obj_type_t remaining; + pcb_obj_type_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_obj_type_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_obj_type_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/1.2.7/src/data_list.h =================================================================== --- tags/1.2.7/src/data_list.h (nonexistent) +++ tags/1.2.7/src/data_list.h (revision 13657) @@ -0,0 +1,37 @@ +/* + * 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. + * + */ + +#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 */ +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/1.2.7/src/data_parent.h =================================================================== --- tags/1.2.7/src/data_parent.h (nonexistent) +++ tags/1.2.7/src/data_parent.h (revision 13657) @@ -0,0 +1,68 @@ +/* + * 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. + * + */ + +#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_ELEMENT, /* object is part of an element */ + 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_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_element_t *element; + pcb_subc_t *subc; + pcb_board_t *board; +}; + +#define PCB_PARENT_TYPENAME_layer PCB_PARENT_LAYER +#define PCB_PARENT_TYPENAME_data PCB_PARENT_DATA +#define PCB_PARENT_TYPENAME_element PCB_PARENT_ELEMENT +#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/1.2.7/src/default2.lht =================================================================== --- tags/1.2.7/src/default2.lht (nonexistent) +++ tags/1.2.7/src/default2.lht (revision 13657) @@ -0,0 +1,151 @@ +# pcb-rnd official 2-layer default board + +ha:pcb-rnd-board-v4 { + ha:attributes { + {PCB::grid::unit}=mil + } + + 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: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: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=7; } + ha:bottom-vcc { lid=5; group=5; } + 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: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 { outline=1; intern=1; } + 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; } + } + } + } + + 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 = 5.00000 in + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 200000000.2 + max_width = 6.00000 in + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + grid_unit = mil + } + } + } +} Index: tags/1.2.7/src/default4.lht =================================================================== --- tags/1.2.7/src/default4.lht (nonexistent) +++ tags/1.2.7/src/default4.lht (revision 13657) @@ -0,0 +1,171 @@ +# pcb-rnd official 4-layer default board + +ha:pcb-rnd-board-v4 { + ha:attributes { + {PCB::grid::unit}=mil + } + + 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: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: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: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 { outline=1; intern=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 { + 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 = 5.00000 in + line_thickness = 10.00 mil + shrink = 9.00 mil + poly_isle_area = 200000000.2 + max_width = 6.00000 in + min_wid = 10.00 mil + bloat = 12.00 mil + min_drill = 15.00 mil + } + ha:editor { + grid_unit = mil + } + } + } +} Index: tags/1.2.7/src/default_font =================================================================== --- tags/1.2.7/src/default_font (nonexistent) +++ tags/1.2.7/src/default_font (revision 13657) @@ -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/1.2.7/src/dolists.h =================================================================== --- tags/1.2.7/src/dolists.h (nonexistent) +++ tags/1.2.7/src/dolists.h (revision 13657) @@ -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/1.2.7/src/draw.c =================================================================== --- tags/1.2.7/src/draw.c (nonexistent) +++ tags/1.2.7/src/draw.c (revision 13657) @@ -0,0 +1,967 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* drawing routines + */ + +#include "config.h" + +#include "conf_core.h" +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "draw.h" +#include "rotate.h" +#include "rtree.h" +#include "stub_draw.h" +#include "obj_all.h" +#include "layer_ui.h" + +#include "obj_pad_draw.h" +#include "obj_pinvia_draw.h" +#include "obj_pstk_draw.h" +#include "obj_elem_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" + +#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_doing_pinout = 0; +pcb_bool pcb_draw_doing_assy = pcb_false; +static vtp0_t delayed_labels; +pcb_bool delayed_labels_enabled = pcb_false; + +static void DrawEverything(const pcb_box_t *); +static void DrawLayerGroup(int, const pcb_box_t *, int); +static void pcb_draw_obj_label(pcb_layergrp_id_t gid, pcb_any_obj_t *obj); +static void pcb_draw_pstk_marks(const pcb_box_t *drawn_area); +static void pcb_draw_pstk_holes(pcb_layergrp_id_t group, const pcb_box_t *drawn_area, pcb_pstk_draw_hole_t holetype); + +/* In draw_ly_spec.c: */ +static void pcb_draw_paste(int side, const pcb_box_t *drawn_area); +static void pcb_draw_mask(int side, const pcb_box_t *screen); +static void pcb_draw_silk(unsigned long lyt_side, const pcb_box_t *drawn_area); +static void pcb_draw_rats(const pcb_box_t *); +static void pcb_draw_assembly(unsigned int lyt_side, const pcb_box_t *drawn_area); + + +void pcb_draw_delay_label_add(pcb_any_obj_t *obj) +{ + if (delayed_labels_enabled) + vtp0_append(&delayed_labels, obj); +} + + +#warning cleanup TODO: this should be cached +void pcb_lighten_color(const char *orig, char buf[8], double factor) +{ + unsigned int r, g, b; + + if (orig[0] == '#') { + sscanf(&orig[1], "%2x%2x%2x", &r, &g, &b); + r = MIN(255, r * factor); + g = MIN(255, g * factor); + b = MIN(255, b * factor); + } + else { + r = 0xff; + g = 0xff; + b = 0xff; + } + pcb_snprintf(buf, sizeof("#XXXXXX"), "#%02x%02x%02x", r, g, b); +} + +void pcb_draw_dashed_line(pcb_hid_gc_t GC, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ +/* TODO: we need a real geo lib... using double here is plain wrong */ + double dx = x2-x1, dy = y2-y1; + double len_squared = dx*dx + dy*dy; + int n; + const int segs = 11; /* must be odd */ + + if (len_squared < 1000000) { + /* line too short, just draw it - TODO: magic value; with a proper geo lib this would be gone anyway */ + pcb_gui->draw_line(GC, x1, y1, x2, y2); + return; + } + + /* 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 DrawHoles(pcb_bool draw_plated, pcb_bool draw_unplated, const pcb_box_t * drawn_area) +{ + int plated = -1; + + if (draw_plated && !draw_unplated) + plated = 1; + if (!draw_plated && draw_unplated) + plated = 0; + + pcb_r_search(PCB->Data->pin_tree, drawn_area, NULL, pcb_hole_draw_callback, &plated, NULL); + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, pcb_hole_draw_callback, &plated, NULL); +} + +static void DrawEverything_holes(pcb_layergrp_id_t gid, const pcb_box_t *drawn_area) +{ + int plated, unplated; + pcb_board_count_holes(PCB, &plated, &unplated, drawn_area); + + if (plated && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_PLATED_DRILL, 0)) { + DrawHoles(pcb_true, pcb_false, drawn_area); + pcb_draw_pstk_holes(gid, drawn_area, PCB_PHOLE_PLATED); + pcb_gui->end_layer(); + } + + if (unplated && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_UNPLATED_DRILL, 0)) { + DrawHoles(pcb_false, pcb_true, drawn_area); + pcb_draw_pstk_holes(gid, drawn_area, PCB_PHOLE_UNPLATED); + pcb_gui->end_layer(); + } +} + +/* --------------------------------------------------------------------------- + * initializes some identifiers for a new zoom factor and redraws whole screen + */ +static void DrawEverything(const pcb_box_t * drawn_area) +{ + int i, ngroups, side, slk_len; + pcb_layergrp_id_t component, solder, slk[16], gid, side_copper_grp; + /* This is the list of layer groups we will draw. */ + pcb_layergrp_id_t 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_layer_t *first; + pcb_hid_expose_ctx_t hid_exp; + pcb_bool paste_empty; + + hid_exp.view = *drawn_area; + hid_exp.force = 0; + + PCB->Data->SILKLAYER.meta.real.color = conf_core.appearance.color.element; + PCB->Data->BACKSILKLAYER.meta.real.color = conf_core.appearance.color.invisible_objects; + + pcb_gui->render_burst(PCB_HID_BURST_START, 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_MASK) || (gflg & PCB_LYT_PASTE)) /* do not draw silk, mask and paste 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 = PCB_SWAP_IDENT ? solder : component; + + + /* + * first draw all 'invisible' stuff + */ + if (!conf_core.editor.check_planes && pcb_layer_gui_set_vlayer(PCB, PCB_VLY_INVISIBLE, 0)) { + side = PCB_SWAP_IDENT ? PCB_COMPONENT_SIDE : PCB_SOLDER_SIDE; + pcb_draw_silk(PCB_LYT_INVISIBLE_SIDE(), 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->pad_tree, drawn_area, NULL, pcb_pad_draw_callback, &side, NULL); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + + pcb_gui->end_layer(); + } + + /* 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)) { + 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; + } + + DrawLayerGroup(group, drawn_area, is_current); + pcb_gui->end_layer(); + } + } + + if (conf_core.editor.check_planes && pcb_gui->gui) + goto finish; + + /* Draw pins, pads, vias below silk */ + 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); + if (pcb_gui->gui) + pcb_draw_ppv(PCB_SWAP_IDENT ? solder : component, drawn_area); + else if (!pcb_gui->holes_after) + DrawEverything_holes(side_copper_grp, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, 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))) { + pcb_draw_mask(PCB_COMPONENT_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + gid = pcb_layergrp_get_bottom_mask(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, 0))) { + pcb_draw_mask(PCB_SOLDER_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + /* Draw silks */ + slk_len = pcb_layergrp_list(PCB, PCB_LYT_SILK, slk, sizeof(slk) / sizeof(slk[0])); + for(i = 0; i < slk_len; i++) { + if (pcb_layer_gui_set_glayer(PCB, slk[i], 0)) { + unsigned int loc = pcb_layergrp_flags(PCB, slk[i]); + pcb_draw_silk(loc & PCB_LYT_ANYWHERE, drawn_area); + pcb_gui->end_layer(); + } + } + + if (pcb_gui->holes_after) + { + 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); + DrawEverything_holes(side_copper_grp, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + } + + gid = pcb_layergrp_get_top_paste(); + if (gid < 0) + paste_empty = pcb_layer_is_paste_auto_empty(PCB, PCB_COMPONENT_SIDE); + else + paste_empty = pcb_layergrp_is_empty(PCB, gid); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, paste_empty))) { + pcb_draw_paste(PCB_COMPONENT_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + gid = pcb_layergrp_get_bottom_paste(); + if (gid < 0) + paste_empty = pcb_layer_is_paste_auto_empty(PCB, PCB_SOLDER_SIDE); + else + paste_empty = pcb_layergrp_is_empty(PCB, gid); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(PCB, gid, paste_empty))) { + pcb_draw_paste(PCB_SOLDER_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_TOP_ASSY, 0)) { + pcb_draw_assembly(PCB_LYT_TOP, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_BOTTOM_ASSY, 0)) { + pcb_draw_assembly(PCB_LYT_BOTTOM, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_FAB, 0)) { + pcb_stub_draw_fab(pcb_draw_out.fgGC, &hid_exp); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_CSECT, 0)) { + pcb_stub_draw_csect(pcb_draw_out.fgGC, &hid_exp); + pcb_gui->end_layer(); + } + + if (pcb_gui->gui) { + /* Draw element Marks */ + 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); + + if (PCB->PinOn) + pcb_r_search(PCB->Data->element_tree, drawn_area, NULL, pcb_elem_mark_draw_callback, NULL, NULL); + + if (PCB->SubcOn) + pcb_r_search(PCB->Data->subc_tree, drawn_area, NULL, draw_subc_mark_callback, NULL, NULL); + + if (PCB->padstack_mark_on) + pcb_draw_pstk_marks(drawn_area); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + + /* Draw rat lines on top */ + if (pcb_layer_gui_set_vlayer(PCB, PCB_VLY_RATS, 0)) { + 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(); + } + + /* Draw pins' and pads' names */ + 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_ppv_names(PCB_SWAP_IDENT ? solder : component, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + } + + /* find the first ui layer in use */ + first = NULL; + for(i = 0; i < vtlayer_len(&pcb_uilayer); i++) { + if (pcb_uilayer.array[i].meta.real.cookie != NULL) { + first = pcb_uilayer.array+i; + break; + } + } + + /* if there's any UI layer, try to draw them */ + if ((first != NULL) && pcb_layer_gui_set_g_ui(first, 0)) { + int have_canvas = 0; + for(i = 0; i < vtlayer_len(&pcb_uilayer); i++) + if ((pcb_uilayer.array[i].meta.real.cookie != NULL) && (pcb_uilayer.array[i].meta.real.vis)) { + if (!have_canvas) { + 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); + have_canvas = 1; + } + pcb_draw_layer(pcb_uilayer.array+i, drawn_area); + } + pcb_gui->end_layer(); + if (have_canvas) + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); + } + + + finish:; + pcb_gui->render_burst(PCB_HID_BURST_END, drawn_area); +} + +static void pcb_draw_pstks(pcb_layergrp_id_t group, const pcb_box_t *drawn_area, int is_current, pcb_layer_combining_t comb) +{ + pcb_pstk_draw_t ctx; + ctx.pcb = PCB; + ctx.gid = group; + ctx.is_current = is_current; + ctx.comb = comb; + pcb_r_search(PCB->Data->padstack_tree, drawn_area, NULL, pcb_pstk_draw_callback, &ctx, NULL); +} + +static void pcb_draw_pstk_marks(const pcb_box_t *drawn_area) +{ + pcb_pstk_draw_t ctx; + ctx.pcb = PCB; + pcb_r_search(PCB->Data->padstack_tree, drawn_area, NULL, pcb_pstk_draw_mark_callback, &ctx, NULL); +} + +static void pcb_draw_pstk_holes(pcb_layergrp_id_t group, const pcb_box_t *drawn_area, pcb_pstk_draw_hole_t holetype) +{ + pcb_pstk_draw_t ctx; + ctx.pcb = PCB; + ctx.gid = group; + ctx.holetype = holetype; + pcb_r_search(PCB->Data->padstack_tree, drawn_area, NULL, pcb_pstk_draw_hole_callback, &ctx, NULL); +} + +/* --------------------------------------------------------------------------- + * Draws pins pads and vias - Always draws for non-gui HIDs, + * otherwise drawing depends on PCB->PinOn and PCB->ViaOn + */ +void pcb_draw_ppv(pcb_layergrp_id_t group, const pcb_box_t * drawn_area) +{ + int side; + unsigned int gflg = pcb_layergrp_flags(PCB, group); + + if (PCB->PinOn || !pcb_gui->gui) { + /* draw element pins */ + pcb_r_search(PCB->Data->pin_tree, drawn_area, NULL, pcb_pin_draw_callback, NULL, NULL); + + /* draw element pads */ + if (gflg & PCB_LYT_TOP) { + side = PCB_COMPONENT_SIDE; + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, pcb_pad_draw_callback, &side, NULL); + } + + if (gflg & PCB_LYT_BOTTOM) { + side = PCB_SOLDER_SIDE; + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, pcb_pad_draw_callback, &side, NULL); + } + } + + /* draw vias */ + if (PCB->ViaOn || !pcb_gui->gui) { + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, pcb_via_draw_callback, NULL, NULL); + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, pcb_hole_draw_callback, NULL, NULL); + } + if (PCB->PinOn || pcb_draw_doing_assy) + pcb_r_search(PCB->Data->pin_tree, drawn_area, NULL, pcb_hole_draw_callback, NULL, NULL); + + + /* draw padstack holes - copper is drawn with each group */ + if (PCB->ViaOn || !pcb_gui->gui) + pcb_draw_pstk_holes(group, drawn_area, PCB_PHOLE_PLATED | PCB_PHOLE_UNPLATED | PCB_PHOLE_BB); +} + +/* --------------------------------------------------------------------------- + * Draws pins' and pads' names - Always draws for non-gui HIDs, + * otherwise drawing depends on PCB->PinOn and PCB->ViaOn + */ +void pcb_draw_ppv_names(pcb_layergrp_id_t group, const pcb_box_t * drawn_area) +{ + int side; + unsigned int gflg = pcb_layergrp_flags(PCB, group); + + if (PCB->PinOn || !pcb_gui->gui) { + /* draw element pins' names */ + pcb_r_search(PCB->Data->pin_tree, drawn_area, NULL, pcb_pin_name_draw_callback, NULL, NULL); + + /* draw element pads' names */ + if (gflg & PCB_LYT_TOP) { + side = PCB_COMPONENT_SIDE; + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, pcb_pad_name_draw_callback, &side, NULL); + } + + if (gflg & PCB_LYT_BOTTOM) { + side = PCB_SOLDER_SIDE; + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, pcb_pad_name_draw_callback, &side, NULL); + } + } + + if (PCB->ViaOn || !pcb_gui->gui) { + /* draw element pins' names */ + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, pcb_pin_name_draw_callback, NULL, NULL); + } + + if (PCB->PinOn || !pcb_gui->gui) { + size_t n; + for(n = 0; n < delayed_labels.used; n++) + pcb_draw_obj_label(group, delayed_labels.array[n]); + } + delayed_labels.used = 0; +} + +#include "draw_composite.c" +#include "draw_ly_spec.c" + +void pcb_draw_layer(pcb_layer_t *Layer, const pcb_box_t * screen) +{ + pcb_draw_info_t info; + pcb_box_t scr2; + unsigned int lflg = 0; + + 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.drawn_area = screen; + info.layer = 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; + + if (lflg & PCB_LYT_COPPER) { + /* print the non-clearing polys */ + pcb_r_search(Layer->polygon_tree, screen, NULL, pcb_poly_draw_term_callback, &info, NULL); + } + else { + /* print the non-clearing polys */ + pcb_r_search(Layer->polygon_tree, screen, NULL, pcb_poly_draw_callback, &info, NULL); + } + + if (conf_core.editor.check_planes) + goto out; + + if (lflg & PCB_LYT_COPPER) { + /* draw all visible lines this layer - with terminal gfx */ + pcb_r_search(Layer->line_tree, screen, NULL, pcb_line_draw_term_callback, Layer, NULL); + + /* draw the layer arcs on screen */ + pcb_r_search(Layer->arc_tree, screen, NULL, pcb_arc_draw_term_callback, Layer, NULL); + + /* draw the layer text on screen */ + pcb_r_search(Layer->text_tree, screen, NULL, pcb_text_draw_term_callback, Layer, NULL); + } + else { + /* draw all visible lines this layer */ + pcb_r_search(Layer->line_tree, screen, NULL, pcb_line_draw_callback, Layer, NULL); + + /* draw the layer arcs on screen */ + pcb_r_search(Layer->arc_tree, screen, NULL, pcb_arc_draw_callback, Layer, NULL); + + /* draw the layer text on screen */ + pcb_r_search(Layer->text_tree, screen, NULL, pcb_text_draw_callback, Layer, NULL); + } + + /* 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. */ + if ((lflg & PCB_LYT_OUTLINE) && pcb_layer_is_empty_(PCB, Layer)) { + pcb_gui->set_color(pcb_draw_out.fgGC, Layer->meta.real.color); + pcb_gui->set_line_width(pcb_draw_out.fgGC, PCB->minWid); + pcb_gui->draw_rect(pcb_draw_out.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight); + } + + out:; + pcb_draw_out.active_padGC = NULL; +} + +/* --------------------------------------------------------------------------- + * draws one layer group. If the exporter is not a GUI, + * also draws the pins / pads / vias in this layer group. + */ +static void DrawLayerGroup(int group, const pcb_box_t *drawn_area, int is_current) +{ + int i, rv = 1; + 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; + unsigned int gflg = pcb_layergrp_flags(PCB, group); + + 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); + + if (gflg & PCB_LYT_OUTLINE) + rv = 0; + + for (i = n_entries - 1; i >= 0; i--) { + layernum = layers[i]; + Layer = PCB->Data->Layer + layernum; + if (!(gflg & PCB_LYT_SILK) && Layer->meta.real.vis) + pcb_draw_layer(Layer, drawn_area); + } + if (n_entries > 1) + rv = 1; + + if (gflg & PCB_LYT_COPPER) + pcb_draw_pstks(group, drawn_area, (CURRENT->meta.real.grp == group), 0); + + /* this draws the holes - must be the last, so holes are drawn over everything else */ + if (rv && !pcb_gui->gui) + pcb_draw_ppv(group, drawn_area); + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, drawn_area); +} + +void pcb_erase_obj(int type, void *lptr, void *ptr) +{ + switch (type) { + case PCB_TYPE_VIA: + case PCB_TYPE_PIN: + pcb_pin_invalidate_erase((pcb_pin_t *) ptr); + break; + case PCB_TYPE_TEXT: + case PCB_TYPE_ELEMENT_NAME: + pcb_text_invalidate_erase((pcb_layer_t *) lptr, (pcb_text_t *) ptr); + break; + case PCB_TYPE_POLY: + pcb_poly_invalidate_erase((pcb_poly_t *) ptr); + break; + case PCB_TYPE_ELEMENT: + pcb_elem_invalidate_erase((pcb_element_t *) ptr); + break; + case PCB_TYPE_SUBC: + EraseSubc((pcb_subc_t *)ptr); + break; + case PCB_TYPE_LINE: + case PCB_TYPE_ELEMENT_LINE: + case PCB_TYPE_RATLINE: + pcb_line_invalidate_erase((pcb_line_t *) ptr); + break; + case PCB_TYPE_PAD: + pcb_pad_invalidate_erase((pcb_pad_t *) ptr); + break; + case PCB_TYPE_ARC: + case PCB_TYPE_ELEMENT_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) +{ + switch (obj->type) { + case PCB_OBJ_VIA: + if (PCB->ViaOn) + pcb_via_invalidate_draw((pcb_pin_t *)obj); + break; + case PCB_OBJ_PSTK: + if (PCB->ViaOn) + 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_ELEMENT: + if (pcb_silk_on(PCB) && (PCB_FRONT((pcb_element_t *)obj) || PCB->InvisibleObjectsOn)) + pcb_elem_invalidate_draw((pcb_element_t *)obj); + break; + case PCB_OBJ_RAT: + if (PCB->RatOn) + pcb_rat_invalidate_draw((pcb_rat_t *)obj); + break; + case PCB_OBJ_PIN: + if (PCB->PinOn) + pcb_pin_invalidate_draw((pcb_pin_t *)obj); + break; + case PCB_OBJ_PAD: + if (PCB->PinOn) + pcb_pad_invalidate_draw((pcb_pad_t *)obj); + break; + case PCB_OBJ_ETEXT: + if (pcb_silk_on(PCB) && (PCB_FRONT(obj->parent.element) || PCB->InvisibleObjectsOn)) + pcb_elem_name_invalidate_draw(obj->parent.element); + break; + case PCB_OBJ_POINT: + case PCB_OBJ_SUBC: + case PCB_OBJ_NET: + case PCB_OBJ_LAYER: + case PCB_OBJ_ELINE: + case PCB_OBJ_EARC: + case PCB_OBJ_VOID: + break; + } +} + +static void pcb_draw_obj_label(pcb_layergrp_id_t gid, pcb_any_obj_t *obj) +{ + /* do not show layer-object labels of the other side on non-pinout views */ + if ((!pcb_draw_doing_pinout) && (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((pcb_line_t *)obj); return; + case PCB_OBJ_ARC: pcb_arc_draw_label((pcb_arc_t *)obj); return; + case PCB_OBJ_POLY: pcb_poly_draw_label((pcb_poly_t *)obj); return; + case PCB_OBJ_TEXT: pcb_text_draw_label((pcb_text_t *)obj); return; + case PCB_OBJ_PSTK: pcb_pstk_draw_label((pcb_pstk_t *)obj); return; + default: break; + } +} + +/* --------------------------------------------------------------------------- + * HID drawing callback. + */ + +static pcb_hid_t *expose_begin(pcb_hid_t *hid) +{ + pcb_hid_t *old_gui = pcb_gui; + + delayed_labels_enabled = pcb_true; + vtp0_truncate(&delayed_labels, 0); + + pcb_gui = hid; + pcb_draw_out.fgGC = pcb_gui->make_gc(); + pcb_draw_out.padGC = pcb_gui->make_gc(); + pcb_draw_out.backpadGC = pcb_gui->make_gc(); + pcb_draw_out.padselGC = pcb_gui->make_gc(); + pcb_draw_out.drillGC = pcb_gui->make_gc(); + pcb_draw_out.pmGC = pcb_gui->make_gc(); + if (hid->force_compositing) + pcb_draw_out.direct = 0; + else + pcb_draw_out.direct = 1; + + hid->set_color(pcb_draw_out.pmGC, "erase"); + hid->set_color(pcb_draw_out.drillGC, "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.pin_selected); + + return old_gui; +} + +static void expose_end(pcb_hid_t *old_gui) +{ + pcb_gui->destroy_gc(pcb_draw_out.fgGC); + pcb_gui->destroy_gc(pcb_draw_out.padGC); + pcb_gui->destroy_gc(pcb_draw_out.backpadGC); + pcb_gui->destroy_gc(pcb_draw_out.padselGC); + pcb_gui->destroy_gc(pcb_draw_out.drillGC); + pcb_gui->destroy_gc(pcb_draw_out.pmGC); + pcb_gui = old_gui; + + delayed_labels_enabled = pcb_false; + vtp0_truncate(&delayed_labels, 0); +} + +void pcb_hid_expose_all(pcb_hid_t * hid, const pcb_hid_expose_ctx_t *ctx) +{ + if (!pcb_draw_inhibit) { + pcb_hid_t *old_gui = expose_begin(hid); + DrawEverything(&ctx->view); + expose_end(old_gui); + } +} + +void pcb_hid_expose_pinout(pcb_hid_t * hid, const pcb_hid_expose_ctx_t *ctx) +{ + pcb_hid_t *old_gui = expose_begin(hid); + int fx, fy, fs; + + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, &ctx->view); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 1, &ctx->view); + + 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); + + if (ctx->content.obj != NULL) { + pcb_draw_doing_pinout = pcb_true; + switch(ctx->content.obj->type) { + case PCB_OBJ_ELEMENT: pcb_elem_draw((pcb_element_t *)ctx->content.obj); break; + case PCB_OBJ_SUBC: pcb_subc_draw_preview((pcb_subc_t *)ctx->content.obj, &ctx->view); break; + default: pcb_message(PCB_MSG_ERROR, "pcb_hid_expose_pinout: unknown object type %x\n", ctx->content.obj->type); + } + pcb_draw_doing_pinout = pcb_false; + } + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, &ctx->view); + + 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); + + expose_end(old_gui); +} + +void pcb_hid_expose_layer(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *e) +{ + pcb_hid_t *old_gui = expose_begin(hid); + unsigned long lflg = pcb_layer_flags(PCB, e->content.layer_id); + int fx, fy; + + if (lflg & PCB_LYT_LOGICAL) { + fx = conf_core.editor.view.flip_x; + fy = conf_core.editor.view.flip_y; + conf_force_set_bool(conf_core.editor.view.flip_x, 0); + conf_force_set_bool(conf_core.editor.view.flip_y, 0); + } + + if (lflg & PCB_LYT_CSECT) { + if ((pcb_layer_gui_set_vlayer(PCB, PCB_VLY_CSECT, 0)) || (e->force)) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, &e->view); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 1, &e->view); + pcb_stub_draw_csect(pcb_draw_out.fgGC, e); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, &e->view); + pcb_gui->end_layer(); + } + } + else if (lflg & PCB_LYT_DIALOG) { + if ((pcb_layer_gui_set_vlayer(PCB, PCB_VLY_DIALOG, 0)) || (e->force)) { + 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->dialog_draw(pcb_draw_out.fgGC, e); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, &e->view); + pcb_gui->end_layer(); + } + } + else if ((e->content.layer_id >= 0) && (e->content.layer_id < pcb_max_layer)) { + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, 1, &e->view); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, 1, &e->view); + pcb_draw_layer(&(PCB->Data->Layer[e->content.layer_id]), &e->view); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, 1, &e->view); + } + else + pcb_message(PCB_MSG_ERROR, "Internal error: don't know how to draw layer %ld for preview; please report this bug.\n", e->content.layer_id); + + expose_end(old_gui); + + if (lflg & PCB_LYT_LOGICAL) { + conf_force_set_bool(conf_core.editor.view.flip_x, fx); + conf_force_set_bool(conf_core.editor.view.flip_y, fy); + } +} + +static const char *lab_with_intconn(int intconn, const char *lab, char *buff, int bufflen) +{ + if (intconn <= 0) + return lab; + pcb_snprintf(buff, bufflen, "%s[%d]", lab, intconn); + return buff; +} + +static void pcb_term_label_setup_(pcb_text_t *text, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *label) +{ + pcb_bool flip_x = conf_core.editor.view.flip_x; + pcb_bool flip_y = conf_core.editor.view.flip_y; + + text->TextString = (char *)label; + text->Flags = (flip_x ^ flip_y) ? pcb_flag_make(PCB_FLAG_ONSOLDER) : pcb_no_flags(); + text->X = x; + text->Y = y; + text->fid = 0; + text->Scale = scale; + text->Direction = (vert ? 1 : 0) + (flip_x ? 2 : 0); + + pcb_text_bbox(NULL, text); + + if (centered) { + pcb_coord_t dx, dy; + dx = (text->BoundingBox.X2 - text->BoundingBox.X1) / 2; + dy = (text->BoundingBox.Y2 - text->BoundingBox.Y1) / 2; + + /* make sure the offset is in-line with the flip and our sick y coords for vertical */ + if ((vert) && (!(flip_x ^ flip_y))) + dy = -dy; + if (flip_x) + dx = -dx; + if (flip_y) + dy = -dy; + + text->X -= dx; + text->Y -= dy; + text->BoundingBox.X1 -= dx; + text->BoundingBox.X2 -= dx; + text->BoundingBox.Y1 -= dy; + text->BoundingBox.Y2 -= dy; + } +} + +void pcb_term_label_setup(pcb_text_t *text, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *lab, int intconn) +{ + const char *label; + char buff[128]; + + label = lab_with_intconn(intconn, lab, buff, sizeof(buff)); + pcb_term_label_setup_(text, x, y, scale, vert, centered, label); +} + + +void pcb_term_label_draw(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *lab, int intconn) +{ + pcb_text_t text; + const char *label; + char buff[128]; + +#warning TODO: split up the label draw functions so we do not need an expensive text object but can just draw low level + memset(&text, 0, sizeof(text)); + label = lab_with_intconn(intconn, lab, buff, sizeof(buff)); + + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.pin_name); + + pcb_term_label_setup_(&text, x, y, scale, vert, centered, label); + + if (pcb_gui->gui) + pcb_draw_doing_pinout++; + pcb_text_draw_(&text, 0, 0); + if (pcb_gui->gui) + pcb_draw_doing_pinout--; +} + Index: tags/1.2.7/src/draw.h =================================================================== --- tags/1.2.7/src/draw.h (nonexistent) +++ tags/1.2.7/src/draw.h (revision 13657) @@ -0,0 +1,127 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_DRAW_H +#define PCB_DRAW_H + +#include "config.h" +#include "hid.h" + +typedef struct { /* holds information about output window */ + pcb_hid_gc_t drillGC, /* drill and foreground; */ + fgGC, /* changed from some routines */ + active_padGC, backpadGC, padGC, padselGC, /* pads are drawn with this gc */ + pmGC; /* depth 1 pixmap GC to store clip */ + 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; + +/* 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) \ + +/* 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_doing_pinout; +extern pcb_bool pcb_draw_doing_assy; + +void pcb_lighten_color(const char *orig, char buf[8], double factor); +void pcb_draw_dashed_line(pcb_hid_gc_t GC, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); + + +void pcb_draw(void); +void pcb_redraw(void); +void pcb_draw_obj(pcb_any_obj_t *obj); +void pcb_draw_layer(pcb_layer_t *, const pcb_box_t *); +void pcb_erase_obj(int, void *, void *); +void pcb_draw_ppv(pcb_layergrp_id_t group, const pcb_box_t * drawn_area); +void pcb_draw_ppv_names(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_gui->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 + +/* Some low level draw callback depend on this in their void *cl */ +typedef struct pcb_draw_info_s { + const pcb_box_t *drawn_area; + pcb_layer_t *layer; +} pcb_draw_info_t; + +/* 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(pcb_layergrp_t *g); + +/* Draw (render) a terminal label */ +void pcb_term_label_draw(pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *lab, int intconn); + +/* Similar to pcb_term_label_draw(), but doesn't draw only sets up text with + its bounding box */ +void pcb_term_label_setup(pcb_text_t *text, pcb_coord_t x, pcb_coord_t y, double scale, pcb_bool vert, pcb_bool centered, const char *lab, int intconn); + + +/* 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_GFX_WIDTH (-3) + +#endif Index: tags/1.2.7/src/draw_composite.c =================================================================== --- tags/1.2.7/src/draw_composite.c (nonexistent) +++ tags/1.2.7/src/draw_composite.c (revision 13657) @@ -0,0 +1,181 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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_board_t *pcb; + const pcb_box_t *screen; + pcb_layergrp_t *grp; + pcb_layergrp_id_t gid; + const char *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->screen == NULL) + pcb_gui->fill_rect(pcb_draw_out.fgGC, 0, 0, ctx->pcb->MaxWidth, ctx->pcb->MaxHeight); + else + pcb_gui->fill_rect(pcb_draw_out.fgGC, ctx->screen->X1, ctx->screen->Y1, ctx->screen->X2, ctx->screen->Y2); +} + +static void comp_start_sub_(comp_ctx_t *ctx) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_NEGATIVE, pcb_draw_out.direct, ctx->screen); +} + +static void comp_start_add_(comp_ctx_t *ctx) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, ctx->screen); +} + +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->screen); + 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->screen); + 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->screen); + return; + } + + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, ctx->screen); +} + +static void comp_init(comp_ctx_t *ctx, int negative) +{ + pcb_gui->set_drawing_mode(PCB_HID_COMP_RESET, pcb_draw_out.direct, ctx->screen); + + 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->screen); + 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; + } + + { + const char *old_color = l->meta.real.color; + pcb_hid_gc_t old_fg = pcb_draw_out.fgGC; + pcb_draw_out.fgGC = pcb_draw_out.pmGC; + l->meta.real.color = ctx->color; + if (!want_add) + l->meta.real.color = "erase"; + if (l->comb & PCB_LYC_AUTO) + draw_auto(ctx, auto_data); + pcb_draw_layer(l, ctx->screen); + l->meta.real.color = old_color; + pcb_draw_out.fgGC = old_fg; + } + } + if (!adding) + comp_start_add(ctx); +} + +int pcb_draw_layergrp_is_comp(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); +} Index: tags/1.2.7/src/draw_ly_spec.c =================================================================== --- tags/1.2.7/src/draw_ly_spec.c (nonexistent) +++ tags/1.2.7/src/draw_ly_spec.c (revision 13657) @@ -0,0 +1,191 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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) +{ + pcb_pad_paste_draw(*(int *)side, ctx->screen); + pcb_draw_pstks(ctx->gid, ctx->screen, 0, PCB_LYC_AUTO); +} + +static void pcb_draw_paste(int side, const pcb_box_t *drawn_area) +{ + unsigned long side_lyt = side ? PCB_LYT_TOP : PCB_LYT_BOTTOM; + pcb_layergrp_id_t gid = -1; + comp_ctx_t cctx; + + pcb_layergrp_list(PCB, PCB_LYT_PASTE | side_lyt, &gid, 1); + + cctx.pcb = PCB; + cctx.screen = drawn_area; + cctx.grp = pcb_get_layergrp(PCB, gid); + cctx.gid = gid; + cctx.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, cctx.screen); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, cctx.screen); + pcb_pad_paste_draw(side, drawn_area); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, cctx.screen); + } + 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) +{ + pcb_r_search(PCB->Data->pin_tree, ctx->screen, NULL, pcb_pin_clear_callback, NULL, NULL); + pcb_r_search(PCB->Data->via_tree, ctx->screen, NULL, pcb_pin_clear_callback, NULL, NULL); + pcb_r_search(PCB->Data->pad_tree, ctx->screen, NULL, pcb_pad_clear_callback, side, NULL); + pcb_draw_pstks(ctx->gid, ctx->screen, 0, PCB_LYC_SUB | PCB_LYC_AUTO); +} + +static void pcb_draw_mask(int side, const pcb_box_t *screen) +{ + unsigned long side_lyt = side ? PCB_LYT_TOP : PCB_LYT_BOTTOM; + pcb_layergrp_id_t gid = -1; + comp_ctx_t cctx; + + pcb_layergrp_list(PCB, PCB_LYT_MASK | side_lyt, &gid, 1); + + cctx.pcb = PCB; + cctx.screen = screen; + cctx.grp = pcb_get_layergrp(PCB, gid); + cctx.gid = gid; + cctx.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) +{ + int side = (*(unsigned long *)lyt_side == PCB_LYT_TOP ? PCB_COMPONENT_SIDE : PCB_SOLDER_SIDE); + + /* draw package */ + pcb_r_search(PCB->Data->element_tree, ctx->screen, NULL, pcb_elem_draw_callback, &side, NULL); + pcb_r_search(PCB->Data->name_tree[PCB_ELEMNAME_IDX_VISIBLE()], ctx->screen, NULL, pcb_elem_name_draw_callback, &side, NULL); + + pcb_draw_pstks(ctx->gid, ctx->screen, 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(unsigned long lyt_side, const pcb_box_t *drawn_area) +{ + pcb_layer_id_t lid; + pcb_layergrp_id_t gid = -1; + comp_ctx_t cctx; + + if (pcb_layer_list(PCB, PCB_LYT_SILK | lyt_side, &lid, 1) == 0) + return; + + pcb_layergrp_list(PCB, PCB_LYT_SILK | lyt_side, &gid, 1); + if (!PCB->LayerGroups.grp[gid].vis) + return; + + cctx.pcb = PCB; + cctx.screen = drawn_area; + cctx.grp = pcb_get_layergrp(PCB, gid); + cctx.gid = gid; + cctx.color = 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 (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, cctx.screen); + pcb_gui->set_drawing_mode(PCB_HID_COMP_POSITIVE, pcb_draw_out.direct, cctx.screen); + pcb_draw_layer(LAYER_PTR(lid), cctx.screen); + pcb_draw_silk_auto(&cctx, &lyt_side); + pcb_gui->set_drawing_mode(PCB_HID_COMP_FLUSH, pcb_draw_out.direct, cctx.screen); + } + else { + comp_draw_layer(&cctx, pcb_draw_silk_auto, &lyt_side); + comp_finish(&cctx); + } +} + + +/******** 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(unsigned int lyt_side, const pcb_box_t *drawn_area) +{ + 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_gui->set_draw_faded(pcb_draw_out.fgGC, 1); + DrawLayerGroup(side_group, drawn_area, 0); + pcb_gui->set_draw_faded(pcb_draw_out.fgGC, 0); + + /* draw package */ + pcb_draw_silk(lyt_side, drawn_area); + pcb_draw_doing_assy = pcb_false; +} Index: tags/1.2.7/src/draw_wireframe.h =================================================================== --- tags/1.2.7/src/draw_wireframe.h (nonexistent) +++ tags/1.2.7/src/draw_wireframe.h (revision 13657) @@ -0,0 +1,102 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#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 wid = arc->Thickness / 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/1.2.7/src/drc.h =================================================================== --- tags/1.2.7/src/drc.h (nonexistent) +++ tags/1.2.7/src/drc.h (revision 13657) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#ifndef PCB_DRC_H +#define PCB_DRC_H + +#include "unit.h" + +struct drc_violation_s { + char *title; + char *explanation; + pcb_coord_t x, y; + pcb_angle_t angle; + int have_measured; + pcb_coord_t measured_value; + pcb_coord_t required_value; + int object_count; + long int *object_id_list; + int *object_type_list; +}; + +typedef struct drc_violation_s pcb_drc_violation_t; + +#endif Index: tags/1.2.7/src/error.c =================================================================== --- tags/1.2.7/src/error.c (nonexistent) +++ tags/1.2.7/src/error.c (revision 13657) @@ -0,0 +1,91 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* error and debug functions */ + +#include "config.h" + +#include +#include + +#include "data.h" +#include "error.h" +#include "plug_io.h" +#include "compat_misc.h" +#include "conf_core.h" + +void pcb_message(enum pcb_message_level level, const char *Format, ...) +{ + va_list args; + pcb_message_level_t min_level = PCB_MSG_INFO; + + if (pcb_gui != NULL) { + va_start(args, Format); + pcb_gui->logv(level, Format, args); + va_end(args); + } + + 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); + } +} + +void pcb_trace(const char *Format, ...) +{ +#ifndef NDEBUG + va_list args; + va_start(args, Format); + pcb_vfprintf(stderr, Format, args); + va_end(args); +#endif +} + + +void pcb_open_error_message(const char *filename) +{ + pcb_message(PCB_MSG_ERROR, "Can't open file\n" " '%s'\nfopen() returned: '%s'\n", filename, strerror(errno)); +} + +void pcb_popen_error_message(const char *filename) +{ + pcb_message(PCB_MSG_ERROR, "Can't execute command\n" " '%s'\npopen() returned: '%s'\n", filename, strerror(errno)); +} + +void pcb_opendir_error_message(const char *dirname) +{ + pcb_message(PCB_MSG_ERROR, "Can't scan directory\n" " '%s'\nopendir() returned: '%s'\n", dirname, strerror(errno)); +} + +void pcb_chdir_error_message(const char *dirname) +{ + pcb_message(PCB_MSG_ERROR, "Can't change working directory to\n" " '%s'\nchdir() returned: '%s'\n", dirname, strerror(errno)); +} Index: tags/1.2.7/src/error.h =================================================================== --- tags/1.2.7/src/error.h (nonexistent) +++ tags/1.2.7/src/error.h (revision 13657) @@ -0,0 +1,52 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Messages, error reporting and debug functions */ + +#ifndef PCB_ERROR_H +#define PCB_ERROR_H + +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; + +/* 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() */ +void pcb_open_error_message(const char *filename); +void pcb_popen_error_message(const char *filename); +void pcb_opendir_error_message(const char *dirname); +void pcb_chdir_error_message(const char *dirname); + +/* pcb_printf()-like call to print temporary trace messages to stderr; + disabled in non-debug compilation */ +void pcb_trace(const char *Format, ...); + +#endif Index: tags/1.2.7/src/event.c =================================================================== --- tags/1.2.7/src/event.c (nonexistent) +++ tags/1.2.7/src/event.c (revision 13657) @@ -0,0 +1,187 @@ +/* + * 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. + * + */ + +#include +#include +#include +#include "config.h" +#include "event.h" +#include "error.h" +#include "fptr_cast.h" + +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; + event_t *e; + int argc; + + a = argv; + a->type = PCB_EVARG_INT; + a->d.i = ev; + argc = 1; + + if (fmt != NULL) { + va_start(ap, fmt); + for (a++; *fmt != '\0'; fmt++, a++, 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; + a->d.i = va_arg(ap, int); + break; + case 'd': + a->type = PCB_EVARG_DOUBLE; + a->d.d = va_arg(ap, double); + break; + case 's': + a->type = PCB_EVARG_STR; + a->d.s = va_arg(ap, const char *); + break; + case 'p': + a->type = PCB_EVARG_PTR; + a->d.p = va_arg(ap, void *); + break; + case 'c': + a->type = PCB_EVARG_COORD; + a->d.c = va_arg(ap, pcb_coord_t); + break; + case 'a': + a->type = PCB_EVARG_ANGLE; + a->d.a = va_arg(ap, pcb_angle_t); + break; + default: + a->type = PCB_EVARG_INT; + a->d.i = 0; + 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); +} + +void pcb_events_init(void) +{ + +} + +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/1.2.7/src/event.h =================================================================== --- tags/1.2.7/src/event.h (nonexistent) +++ tags/1.2.7/src/event.h (revision 13657) @@ -0,0 +1,117 @@ +/* + * 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. + * + */ + +#ifndef PCB_EVENT_H +#define PCB_EVENT_H +#include "config.h" +#include "unit.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_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_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_BUSY, /* called before CPU-intensive task begins */ + + PCB_EVENT_RUBBER_RESET, /* rubber band: reset attached */ + PCB_EVENT_RUBBER_REMOVE_ELEMENT, /* rubber band: removed an element with rubber bands 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_RENAME, /* rubber band: element pin/pad got renamed */ + 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 GUI state (e.g. after a menu clicked) */ + PCB_EVENT_USER_INPUT_POST, /* generated any time any user input reaches core, after processing it */ + + 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 */ +typedef struct { + pcb_event_argtype_t type; + union { + int i; + double d; + const char *s; + void *p; + pcb_coord_t c; + pcb_angle_t a; + } d; +} pcb_event_arg_t; + +/* 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/1.2.7/src/file_act.c =================================================================== --- tags/1.2.7/src/file_act.c (nonexistent) +++ tags/1.2.7/src/file_act.c (revision 13657) @@ -0,0 +1,425 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" + +#include "plug_io.h" +#include "plug_import.h" +#include "remove.h" +#include "draw.h" +#include "find.h" +#include "search.h" +#include "hid_actions.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "hid_init.h" +#include "layer_vis.h" +#include "safe_fs.h" + +/* ---------------------------------------------------------------- */ +static const char pcb_acts_ExecCommand[] = "ExecCommand(command)"; + +static const char pcb_acth_ExecCommand[] = "Runs a command."; + +/* %start-doc actions execcommand + +Runs the given command, which is a system executable. + +%end-doc */ + +static int pcb_act_ExecCommand(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *command; + + if (argc < 1) { + PCB_ACT_FAIL(ExecCommand); + } + + command = PCB_ACTION_ARG(0); + + if (pcb_system(command)) + return 1; + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_LoadFrom[] = "LoadFrom(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename[,format])"; + +static const char pcb_acth_LoadFrom[] = "Load layout data from a file."; + +/* %start-doc actions LoadFrom + +This action assumes you know what the filename is. The various GUIs +should have a similar @code{Load} action where the filename is +optional, and will provide their own file selection mechanism to let +you choose the file name. + +@table @code + +@item Layout +Loads an entire PCB layout, replacing the current one. + +@item LayoutToBuffer +Loads an entire PCB layout to the paste buffer. + +@item ElementToBuffer +Loads the given element file into the paste buffer. Element files +contain only a single @code{Element} definition, such as the +``newlib'' library uses. + +@item Netlist +Loads a new netlist, replacing any current netlist. + +@item Revert +Re-loads the current layout from its disk file, reverting any changes +you may have made. + +@end table + +%end-doc */ + +static int pcb_act_LoadFrom(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function, *name, *format = NULL; + + if (argc < 2) + PCB_ACT_FAIL(LoadFrom); + + function = argv[0]; + name = argv[1]; + if (argc > 2) + format = argv[2]; + + if (pcb_strcasecmp(function, "ElementToBuffer") == 0) { + pcb_notify_crosshair_change(pcb_false); + if (pcb_element_load_to_buffer(PCB_PASTEBUFFER, name)) + pcb_crosshair_set_mode(PCB_MODE_PASTE_BUFFER); + pcb_notify_crosshair_change(pcb_true); + } + + else if (pcb_strcasecmp(function, "LayoutToBuffer") == 0) { + pcb_notify_crosshair_change(pcb_false); + if (pcb_buffer_load_layout(PCB, PCB_PASTEBUFFER, name, format)) + pcb_crosshair_set_mode(PCB_MODE_PASTE_BUFFER); + pcb_notify_crosshair_change(pcb_true); + } + + else if (pcb_strcasecmp(function, "Layout") == 0) { + if (!PCB->Changed || pcb_gui->confirm_dialog(_("OK to override layout data?"), 0)) + pcb_load_pcb(name, format, pcb_true, 0); + } + + else if (pcb_strcasecmp(function, "Netlist") == 0) { + if (PCB->Netlistname) + free(PCB->Netlistname); + PCB->Netlistname = pcb_strdup_strip_wspace(name); + { + int i; + for (i = 0; i < PCB_NUM_NETLISTS; i++) + pcb_lib_free(&(PCB->NetlistLib[i])); + } + if (!pcb_import_netlist(PCB->Netlistname)) + pcb_netlist_changed(1); + } + else if (pcb_strcasecmp(function, "Revert") == 0 && PCB->Filename + && (!PCB->Changed || pcb_gui->confirm_dialog(_("OK to override changes?"), 0))) { + pcb_revert_pcb(); + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_New[] = "New([name])"; + +static const char pcb_acth_New[] = "Starts a new layout."; + +/* %start-doc actions New + +If a name is not given, one is prompted for. + +%end-doc */ + +static int pcb_act_New(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *argument_name = PCB_ACTION_ARG(0); + char *name = NULL; + + if (!PCB->Changed || pcb_gui->confirm_dialog(_("OK to clear layout data?"), 0)) { + if (argument_name) + name = pcb_strdup(argument_name); + else + name = pcb_gui->prompt_for(_("Enter the 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); + + /* 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); + return 0; + } + return 1; +} + +/* --------------------------------------------------------------------------- */ +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 int pcb_act_normalize(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + return pcb_board_normalize(PCB); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SaveTo[] = + "SaveTo(Layout|LayoutAs,filename)\n" + "SaveTo(AllConnections|AllUnusedPins|ElementConnections,filename)\n" "SaveTo(PasteBuffer,filename)"; + +static const char pcb_acth_SaveTo[] = "Saves data to a file."; + +/* %start-doc actions SaveTo + +@table @code + +@item Layout +Saves the current layout. + +@item LayoutAs +Saves the current layout, and remembers the filename used. + +@item AllConnections +Save all connections to a file. + +@item AllUnusedPins +List all unused pins to a file. + +@item ElementConnections +Save connections to the element at the cursor to a file. + +@item PasteBuffer +Save the content of the active Buffer to a file. This is the graphical way to create a footprint. + +@end table + +%end-doc */ + +static int pcb_act_SaveTo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function; + const char *name; + const char *fmt = NULL; + + function = argv[0]; + name = argv[1]; + + if (pcb_strcasecmp(function, "Layout") == 0) { + 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; + } + + if ((argc != 2) && (argc != 3)) + PCB_ACT_FAIL(SaveTo); + + if (argc >= 3) + fmt = argv[2]; + + if (pcb_strcasecmp(function, "LayoutAs") == 0) { + 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; + } + + if (pcb_strcasecmp(function, "AllConnections") == 0) { + FILE *fp; + pcb_bool result; + if ((fp = pcb_check_and_open_file(name, pcb_true, pcb_false, &result, NULL)) != NULL) { + pcb_lookup_conns_to_all_elements(fp); + fclose(fp); + pcb_board_set_changed_flag(pcb_true); + } + return 0; + } + + if (pcb_strcasecmp(function, "AllUnusedPins") == 0) { + FILE *fp; + pcb_bool result; + if ((fp = pcb_check_and_open_file(name, pcb_true, pcb_false, &result, NULL)) != NULL) { + pcb_lookup_unused_pins(fp); + fclose(fp); + pcb_board_set_changed_flag(pcb_true); + } + return 0; + } + + if (pcb_strcasecmp(function, "ElementConnections") == 0) { + pcb_element_t *element; + void *ptrtmp; + FILE *fp; + pcb_bool result; + pcb_coord_t x, y; + + pcb_gui->get_coords("Click on an element", &x, &y); + if ((pcb_search_screen(x, y, PCB_TYPE_ELEMENT, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) { + element = (pcb_element_t *) ptrtmp; + if ((fp = pcb_check_and_open_file(name, pcb_true, pcb_false, &result, NULL)) != NULL) { + pcb_lookup_element_conns(element, fp); + fclose(fp); + pcb_board_set_changed_flag(pcb_true); + } + } + return 0; + } + + if (pcb_strcasecmp(function, "PasteBuffer") == 0) { + return pcb_save_buffer_elements(name, fmt); + } + + PCB_ACT_FAIL(SaveTo); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Quit[] = "Quit()"; + +static const char pcb_acth_Quit[] = "Quits the application after confirming."; + +/* %start-doc actions Quit + +If you have unsaved changes, you will be prompted to confirm (or +save) before quitting. + +%end-doc */ + +static int pcb_act_Quit(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *force = PCB_ACTION_ARG(0); + if (force && pcb_strcasecmp(force, "force") == 0) { + PCB->Changed = 0; + exit(0); + } + if (!PCB->Changed || pcb_gui->close_confirm_dialog() == HID_CLOSE_CONFIRM_OK) + pcb_quit_app(); + return 1; +} + + +/* --------------------------------------------------------------------------- */ +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 int pcb_act_Export(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (argc < 1) { + pcb_message(PCB_MSG_ERROR, "Export() needs at least one argument, the name of the export plugin\n"); + return 1; + } + + pcb_exporter = pcb_hid_find_exporter(argv[0]); + if (pcb_exporter == NULL) { + pcb_message(PCB_MSG_ERROR, "Export plugin %s not found. Was it enabled in ./configure?\n", argv[0]); + return 1; + } + + /* remove the name of the exporter */ + argc--; + argv++; + + /* call the exporter */ + pcb_exporter->parse_arguments(&argc, (char ***)&argv); + pcb_exporter->do_export(NULL); + + pcb_exporter = NULL; + 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 int pcb_act_Backup(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_backup(); + return 0; +} + +pcb_hid_action_t file_action_list[] = { + {"ExecCommand", 0, pcb_act_ExecCommand, + pcb_acth_ExecCommand, pcb_acts_ExecCommand} + , + {"Backup", 0, pcb_act_Backup, + pcb_acth_Backup, pcb_acts_Backup} + , + {"Export", 0, pcb_act_Export, + pcb_acth_Export, pcb_acts_Export} + , + {"LoadFrom", 0, pcb_act_LoadFrom, + pcb_acth_LoadFrom, pcb_acts_LoadFrom} + , + {"New", 0, pcb_act_New, + pcb_acth_New, pcb_acts_New} + , + {"Normalize", 0, pcb_act_normalize, + pcb_acth_normalize, pcb_acts_normalize} + , + {"SaveTo", 0, pcb_act_SaveTo, + pcb_acth_SaveTo, pcb_acts_SaveTo} + , + {"Quit", 0, pcb_act_Quit, + pcb_acth_Quit, pcb_acts_Quit} +}; + +PCB_REGISTER_ACTIONS(file_action_list, NULL) Index: tags/1.2.7/src/find.c =================================================================== --- tags/1.2.7/src/find.c (nonexistent) +++ tags/1.2.7/src/find.c (revision 13657) @@ -0,0 +1,183 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* + * short description: + * - lists for pins and vias, lines, arcs, pads and for polygons are created. + * Every object that has to be checked is added to its list. + * Coarse searching is accomplished with the data rtrees. + * - there's no 'speed-up' mechanism for polygons because they are not used + * as often as other objects + * - the maximum distance between line and pin ... would depend on the angle + * between them. To speed up computation the limit is set to one half + * of the thickness of the objects (cause of square pins). + * + * PV: means pin or via (objects that connect layers) + * LO: all non PV objects (layer objects like lines, arcs, polygons, pads) + * + * 1. first, the LO or PV at the given coordinates is looked up + * 2. all LO connections to that PV are looked up next + * 3. lookup of all LOs connected to LOs from (2). + * This step is repeated until no more new connections are found. + * 4. lookup all PVs connected to the LOs from (2) and (3) + * 5. start again with (1) for all new PVs from (4) + * + */ + +/* routines to find connections between pins, vias, lines... + */ +#include "config.h" + +#include +#include +#include +#include + +#include "const.h" +#include "math_helper.h" +#include "conf_core.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "find.h" +#include "rtree.h" +#include "polygon.h" +#include "search.h" +#include "undo.h" +#include "rats.h" +#include "plug_io.h" +#include "hid_actions.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "layer.h" +#include "event.h" +#include "layer_vis.h" + +#include "obj_all.h" +#include "obj_pstk.h" +#include "obj_text_draw.h" + +#undef DEBUG + +#define SEPARATE(FP) \ + { \ + int i; \ + fputc('#', (FP)); \ + for (i = conf_core.appearance.messages.char_per_line; i; i--) \ + fputc('=', (FP)); \ + fputc('\n', (FP)); \ + } + +#define PADLIST_ENTRY(L,I) \ + (((pcb_pad_t **)PadList[(L)].Data)[(I)]) + +#define LINELIST_ENTRY(L,I) \ + (((pcb_line_t **)LineList[(L)].Data)[(I)]) + +#define ARCLIST_ENTRY(L,I) \ + (((pcb_arc_t **)ArcList[(L)].Data)[(I)]) + +#define RATLIST_ENTRY(I) \ + (((pcb_rat_t **)RatList.Data)[(I)]) + +#define POLYGONLIST_ENTRY(L,I) \ + (((pcb_poly_t **)PolygonList[(L)].Data)[(I)]) + +#define PVLIST_ENTRY(I) \ + (((pcb_pin_t **)PVList.Data)[(I)]) + +#define PADSTACKLIST_ENTRY(I) \ + (((pcb_pstk_t **)PadstackList.Data)[(I)]) + +/* --------------------------------------------------------------------------- + * the two 'dummy' structs for PVs and Pads are necessary for creating + * connection lists which include the element's name + */ +typedef struct { + void **Data; /* pointer to index data */ + pcb_cardinal_t Location, /* currently used position */ + DrawLocation, Number, /* number of objects in list */ + Size; +} ListType, *ListTypePtr; + +static pcb_coord_t Bloat = 0; +static int TheFlag = PCB_FLAG_FOUND; +static int OldFlag = PCB_FLAG_FOUND; +static void *thing_ptr1, *thing_ptr2, *thing_ptr3; +static int thing_type; +pcb_find_callback_t pcb_find_callback = NULL; +#define make_callback(current_type, current_ptr, from_type, from_ptr, type) \ + do { \ + if (pcb_find_callback != NULL) \ + pcb_find_callback(current_type, current_ptr, from_type, from_ptr, type); \ + } while(0) + +static pcb_bool User = pcb_false; /* user action causing this */ +static pcb_bool drc = pcb_false; /* whether to stop if finding something not found */ +static pcb_bool IsBad = pcb_false; +static pcb_cardinal_t drcerr_count; /* count of drc errors */ +static pcb_cardinal_t TotalP, TotalV, NumberOfPads[2], TotalPs; +static ListType LineList[PCB_MAX_LAYER+2], /* list of objects to */ + PolygonList[PCB_MAX_LAYER+2], ArcList[PCB_MAX_LAYER+2], PadList[2], + RatList, PVList, PadstackList; + +static pcb_bool LookupLOConnectionsToPVList(pcb_bool); +static pcb_bool LookupLOConnectionsToPSList(pcb_bool); +static pcb_bool LookupLOConnectionsToLOList(pcb_bool); +static pcb_bool LookupPVPSConnectionsToLOList(pcb_bool); +static pcb_bool LookupPVConnectionsToPVList(void); +static pcb_bool LookupLOConnectionsToLine(pcb_line_t *, pcb_cardinal_t, pcb_bool); +static pcb_bool LookupLOConnectionsToPad(pcb_pad_t *, pcb_cardinal_t); +static pcb_bool LookupLOConnectionsToPolygon(pcb_poly_t *, pcb_cardinal_t); +static pcb_bool LookupLOConnectionsToArc(pcb_arc_t *, pcb_cardinal_t); +static pcb_bool LookupLOConnectionsToRatEnd(pcb_point_t *, pcb_cardinal_t); +static pcb_bool IsRatPointOnLineSpec(pcb_point_t *, pcb_line_t *); +static pcb_bool IsRatPointOnPoly(pcb_point_t *Point, pcb_poly_t *polygon); +static pcb_bool IsRatPointOnArcSpec(pcb_point_t *Point, pcb_arc_t *arc); +static pcb_bool ArcArcIntersect(pcb_arc_t *, pcb_arc_t *); +static pcb_bool PrintElementConnections(pcb_element_t *, FILE *, pcb_bool); +static pcb_bool ListsEmpty(pcb_bool); +static pcb_bool DoIt(pcb_bool, pcb_bool); +static void PrintElementNameList(pcb_element_t *, FILE *); +static void PrintConnectionElementName(pcb_element_t *, FILE *); +static void PrintConnectionListEntry(char *, pcb_element_t *, pcb_bool, FILE *); +static void PrintPadConnections(pcb_cardinal_t, FILE *, pcb_bool); +static void PrintPinConnections(FILE *, pcb_bool); +static void DumpList(void); +static pcb_bool ListStart(pcb_any_obj_t *obj); +static pcb_bool SetThing(int, void *, void *, void *); + + +#include "find_geo.c" +#include "find_lookup.c" +#include "find_drc.c" +#include "find_misc.c" +#include "find_clear.c" + +#include "find_debug.c" +#include "find_print.c" Index: tags/1.2.7/src/find.h =================================================================== --- tags/1.2.7/src/find.h (nonexistent) +++ tags/1.2.7/src/find.h (revision 13657) @@ -0,0 +1,95 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Find galvanic/geometrical connections */ + +#ifndef PCB_FIND_H +#define PCB_FIND_H + +#include /* needed to define 'FILE *' */ +#include "config.h" +#include "obj_common.h" + +typedef enum { + PCB_FCT_COPPER = 1, /* copper connection */ + PCB_FCT_INTERNAL = 2, /* element-internal connection */ + PCB_FCT_RAT = 4, /* connected by a rat line */ + PCB_FCT_ELEMENT = 8, /* pin/pad is part of an element whose pins/pads are being listed */ + PCB_FCT_START = 16 /* starting object of a query */ +} pcb_found_conn_type_t; + +typedef void (*pcb_find_callback_t)(int current_type, void *current_ptr, int from_type, void *from_ptr, + pcb_found_conn_type_t conn_type); + + +/* if not NULL, this function is called whenever something is found + (in LookupConnections for example). The caller should save the original + value and set that back around the call, if the callback needs to be changed. + */ +extern pcb_find_callback_t pcb_find_callback; + +#define PCB_LOOKUP_FIRST \ + (PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_PSTK) +#define PCB_LOOKUP_MORE \ + (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_RATLINE | PCB_TYPE_POLY | PCB_TYPE_ARC | PCB_TYPE_SUBC_PART) +#define PCB_SILK_TYPE \ + (PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY) + +pcb_bool pcb_intersect_line_line(pcb_line_t *, pcb_line_t *); +pcb_bool pcb_intersect_line_arc(pcb_line_t *, pcb_arc_t *); +pcb_bool pcb_intersect_line_pin(pcb_pin_t *, pcb_line_t *); +pcb_bool pcb_intersect_line_pad(pcb_line_t *, pcb_pad_t *); +pcb_bool pcb_intersect_arc_pad(pcb_arc_t *, pcb_pad_t *); +pcb_bool pcb_is_poly_in_poly(pcb_poly_t *, pcb_poly_t *); +void pcb_lookup_element_conns(pcb_element_t *, FILE *); +void pcb_lookup_conns_to_all_elements(FILE *); +void pcb_lookup_conn(pcb_coord_t, pcb_coord_t, pcb_bool, pcb_coord_t, int); +void pcb_lookup_conn_by_pin(int type, void *ptr1); +void pcb_lookup_unused_pins(FILE *); +pcb_bool pcb_reset_found_lines_polys(pcb_bool); +pcb_bool pcb_reset_found_pins_vias_pads(pcb_bool); +pcb_bool pcb_reset_conns(pcb_bool); +void pcb_conn_lookup_init(void); +void pcb_component_lookup_init(void); +void pcb_layout_lookup_init(void); +void pcb_conn_lookup_uninit(void); +void pcb_component_lookup_uninit(void); +void pcb_layout_lookup_uninit(void); +void pcb_rat_find_hook(pcb_any_obj_t *obj, pcb_bool undo, pcb_bool AndRats); +void pcb_save_find_flag(int); +void pcb_restore_find_flag(void); +int pcb_drc_all(void); +pcb_bool pcb_is_line_in_poly(pcb_line_t *, pcb_poly_t *); +pcb_bool pcb_is_arc_in_poly(pcb_arc_t *, pcb_poly_t *); +pcb_bool pcb_is_pad_in_poly(pcb_pad_t *, pcb_poly_t *); + +pcb_cardinal_t pcb_lookup_conn_by_obj(void *ctx, pcb_any_obj_t *obj, pcb_bool AndDraw, pcb_cardinal_t (*cb)(void *ctx, pcb_any_obj_t *obj)); + +/* find_clear.c */ +pcb_bool pcb_clear_flag_on_pins_vias_pads(pcb_bool AndDraw, int flag); +pcb_bool pcb_clear_flag_on_lines_polys(pcb_bool AndDraw, int flag); + +#endif Index: tags/1.2.7/src/find_act.c =================================================================== --- tags/1.2.7/src/find_act.c (nonexistent) +++ tags/1.2.7/src/find_act.c (revision 13657) @@ -0,0 +1,75 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "config.h" +#include "board.h" +#include "conf_core.h" +#include "data.h" +#include "error.h" +#include "find.h" +#include "compat_nls.h" + +/* -------------------------------------------------------------------------- */ + +static const char drc_syntax[] = "DRC()"; + +static const char drc_help[] = "Invoke the DRC check."; + +/* %start-doc actions DRC + +Note that the design rule check uses the current board rule settings, +not the current style settings. + +%end-doc */ + +static int pcb_act_DRCheck(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int count; + + if (pcb_gui->drc_gui == NULL || pcb_gui->drc_gui->log_drc_overview) { + pcb_message(PCB_MSG_INFO, _("%m+Rules are minspace %$mS, minoverlap %$mS " + "minwidth %$mS, minsilk %$mS\n" + "min drill %$mS, min annular ring %$mS\n"), + conf_core.editor.grid_unit->allow, PCB->Bloat, PCB->Shrink, PCB->minWid, PCB->minSlk, PCB->minDrill, PCB->minRing); + } + count = pcb_drc_all(); + if (pcb_gui->drc_gui == NULL || pcb_gui->drc_gui->log_drc_overview) { + if (count == 0) + pcb_message(PCB_MSG_INFO, _("No DRC problems found.\n")); + else if (count > 0) + pcb_message(PCB_MSG_INFO, _("Found %d design rule errors.\n"), count); + else + pcb_message(PCB_MSG_INFO, _("Aborted DRC after %d design rule errors.\n"), -count); + } + return 0; +} + +pcb_hid_action_t find_action_list[] = { + {"DRC", 0, pcb_act_DRCheck, + drc_help, drc_syntax} +}; + +PCB_REGISTER_ACTIONS(find_action_list, NULL) Index: tags/1.2.7/src/find_clear.c =================================================================== --- tags/1.2.7/src/find_clear.c (nonexistent) +++ tags/1.2.7/src/find_clear.c (revision 13657) @@ -0,0 +1,233 @@ +/* + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + */ + +/*! + * \brief Resets all used flags of pins and vias. + */ + +#warning TODO: this file could be removed if ipcd356 used the operation API + +pcb_bool pcb_clear_flag_on_pins_vias_pads(pcb_bool AndDraw, int flag) +{ + pcb_bool change = pcb_false; + + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, via)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_CLEAR(flag, via); + if (AndDraw) + pcb_via_invalidate_draw(via); + change = pcb_true; + } + } + PCB_END_LOOP; + + PCB_PADSTACK_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, padstack)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(padstack); + PCB_FLAG_CLEAR(flag, padstack); + if (AndDraw) + pcb_pstk_invalidate_draw(padstack); + change = pcb_true; + } + } + PCB_END_LOOP; + + + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(flag, pin)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_CLEAR(flag, pin); + if (AndDraw) + pcb_pin_invalidate_draw(pin); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (PCB_FLAG_TEST(flag, pad)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_CLEAR(flag, pad); + if (AndDraw) + pcb_pad_invalidate_draw(pad); + change = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(PCB->Data); + { + PCB_VIA_LOOP(subc->data); + { + if (via->term == NULL) + continue; + if (PCB_FLAG_TEST(flag, via)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_CLEAR(flag, via); + if (AndDraw) + pcb_via_invalidate_draw(via); + change = pcb_true; + } + } + PCB_END_LOOP; + + PCB_LINE_ALL_LOOP(subc->data); + { + if (line->term == NULL) + continue; + if (PCB_FLAG_TEST(flag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(flag, line); + if (AndDraw) + pcb_line_invalidate_draw(layer, line); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + + PCB_ARC_ALL_LOOP(subc->data); + { + if (arc->term == NULL) + continue; + if (PCB_FLAG_TEST(flag, arc)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_CLEAR(flag, arc); + if (AndDraw) + pcb_arc_invalidate_draw(layer, arc); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + + PCB_POLY_ALL_LOOP(subc->data); + { + if (polygon->term == NULL) + continue; + if (PCB_FLAG_TEST(flag, polygon)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_CLEAR(flag, polygon); + if (AndDraw) + pcb_poly_invalidate_draw(layer, polygon); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + + PCB_TEXT_ALL_LOOP(subc->data); + { + if (text->term == NULL) + continue; + if (PCB_FLAG_TEST(flag, text)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_CLEAR(flag, text); + if (AndDraw) + pcb_text_invalidate_draw(layer, text); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + } + PCB_END_LOOP; + + if (change) + pcb_board_set_changed_flag(pcb_true); + return change; +} + +/*! + * \brief Resets all used flags of LOs. + */ +pcb_bool pcb_clear_flag_on_lines_polys(pcb_bool AndDraw, int flag) +{ + pcb_bool change = pcb_false; + + PCB_RAT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(flag, line); + if (AndDraw) + pcb_rat_invalidate_draw(line); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_LINE_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(flag, line); + if (AndDraw) + pcb_line_invalidate_draw(layer, line); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_ARC_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, arc)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_CLEAR(flag, arc); + if (AndDraw) + pcb_arc_invalidate_draw(layer, arc); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_POLY_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(flag, polygon)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_CLEAR(flag, polygon); + if (AndDraw) + pcb_poly_invalidate_draw(layer, polygon); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (change) + pcb_board_set_changed_flag(pcb_true); + return change; +} Index: tags/1.2.7/src/find_deadcode.c =================================================================== --- tags/1.2.7/src/find_deadcode.c (nonexistent) +++ tags/1.2.7/src/find_deadcode.c (revision 13657) @@ -0,0 +1,145 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Dead code - no calls to these functions from anywhere in the code */ +#error do not compile this + + +static int LOT_Linecallback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_intersect_line_line(&i->line, line)) + longjmp(i->env, 1); + return 0; +} + +static int LOT_Arccallback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!arc->Thickness) + return 0; + if (!PCB_FLAG_TEST(TheFlag, arc) && pcb_intersect_line_arc(&i->line, arc)) + longjmp(i->env, 1); + return 0; +} + +static int LOT_Padcallback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) + && pcb_intersect_line_pad(&i->line, pad)) + longjmp(i->env, 1); + return 0; +} + +static pcb_bool PVTouchesLine(pcb_line_t *line) +{ + struct lo_info info; + + info.line = *line; + EXPAND_BOUNDS(&info.line); + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.line, NULL, pv_touch_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.line, NULL, pv_touch_callback, &info, NULL); + else + return pcb_true; + + return (pcb_false); +} + +static pcb_bool LOTouchesLine(pcb_line_t *Line, pcb_cardinal_t LayerGroup) +{ + pcb_cardinal_t entry; + struct lo_info info; + + + /* the maximum possible distance */ + + info.line = *Line; + EXPAND_BOUNDS(&info.line); + + /* loop over all layers of the group */ + for (entry = 0; entry < PCB->LayerGroups.Number[LayerGroup]; entry++) { + pcb_cardinal_t layer = PCB->LayerGroups.Entries[LayerGroup][entry]; + + /* handle normal layers */ + if (layer < pcb_max_copper_layer) { + gdl_iterator_t it; + pcb_poly_t *polygon; + + /* find the first line that touches coordinates */ + + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, (pcb_box_t *) & info.line, NULL, LOT_Linecallback, &info, NULL); + else + return (pcb_true); + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, (pcb_box_t *) & info.line, NULL, LOT_Arccallback, &info, NULL); + else + return (pcb_true); + + /* now check all polygons */ + polylist_foreach(&(PCB->Data->Layer[layer].Polygon), &it, polygon) { + if (!PCB_FLAG_TEST(TheFlag, polygon) + && pcb_is_line_in_poly(Line, polygon)) + return (pcb_true); + } + } + else { + /* handle special 'pad' layers */ + info.layer = layer - pcb_max_copper_layer; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, &info.line.BoundingBox, NULL, LOT_Padcallback, &info, NULL); + else + return pcb_true; + } + } + return (pcb_false); +} + +/* returns pcb_true if nothing un-found touches the passed line + * returns pcb_false if it would touch something not yet found + * doesn't include rat-lines in the search + */ + +pcb_bool lineClear(pcb_line_t *line, pcb_cardinal_t group) +{ + if (LOTouchesLine(line, group)) + return (pcb_false); + if (PVTouchesLine(line)) + return (pcb_false); + return (pcb_true); +} Index: tags/1.2.7/src/find_debug.c =================================================================== --- tags/1.2.7/src/find_debug.c (nonexistent) +++ tags/1.2.7/src/find_debug.c (revision 13657) @@ -0,0 +1,149 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* find-related debug functions */ + +/* --------------------------------------------------------------------------- + * writes the several names of an element to a file + */ +static void PrintElementNameList(pcb_element_t *Element, FILE * FP) +{ + fputc('(', FP); + pcb_print_quoted_string(FP, (char *) PCB_EMPTY(PCB_ELEM_NAME_DESCRIPTION(Element))); + fputc(' ', FP); + pcb_print_quoted_string(FP, (char *) PCB_EMPTY(PCB_ELEM_NAME_REFDES(Element))); + fputc(' ', FP); + pcb_print_quoted_string(FP, (char *) PCB_EMPTY(PCB_ELEM_NAME_VALUE(Element))); + fputc(')', FP); + fputc('\n', FP); +} + +/* --------------------------------------------------------------------------- + * writes the several names of an element to a file + */ +static void PrintConnectionElementName(pcb_element_t *Element, FILE * FP) +{ + fputs("Element", FP); + PrintElementNameList(Element, FP); + fputs("{\n", FP); +} + +/* --------------------------------------------------------------------------- + * prints one {pin,pad,via}/element entry of connection lists + */ +static void PrintConnectionListEntry(char *ObjName, pcb_element_t *Element, pcb_bool FirstOne, FILE * FP) +{ + if (FirstOne) { + fputc('\t', FP); + pcb_print_quoted_string(FP, ObjName); + fprintf(FP, "\n\t{\n"); + } + else { + fprintf(FP, "\t\t"); + pcb_print_quoted_string(FP, ObjName); + fputc(' ', FP); + if (Element) + PrintElementNameList(Element, FP); + else + fputs("(__VIA__)\n", FP); + } +} + +/* --------------------------------------------------------------------------- + * prints all found connections of a pads to file FP + * the connections are stacked in 'PadList' + */ +static void PrintPadConnections(pcb_cardinal_t Layer, FILE * FP, pcb_bool IsFirst) +{ + pcb_cardinal_t i; + pcb_pad_t *ptr; + + if (!PadList[Layer].Number) + return; + + /* the starting pad */ + if (IsFirst) { + ptr = PADLIST_ENTRY(Layer, 0); + if (ptr != NULL) + PrintConnectionListEntry((char *) PCB_UNKNOWN(ptr->Name), NULL, pcb_true, FP); + else + printf("Skipping NULL ptr in 1st part of PrintPadConnections\n"); + } + + /* we maybe have to start with i=1 if we are handling the + * starting-pad itself + */ + for (i = IsFirst ? 1 : 0; i < PadList[Layer].Number; i++) { + ptr = PADLIST_ENTRY(Layer, i); + if (ptr != NULL) + PrintConnectionListEntry((char *) PCB_EMPTY(ptr->Name), (pcb_element_t *) ptr->Element, pcb_false, FP); + else + printf("Skipping NULL ptr in 2nd part of PrintPadConnections\n"); + } +} + +/* --------------------------------------------------------------------------- + * prints all found connections of a pin to file FP + * the connections are stacked in 'PVList' + */ +static void PrintPinConnections(FILE * FP, pcb_bool IsFirst) +{ + pcb_cardinal_t i; + pcb_pin_t *pv; + pcb_pstk_t *ps; + + if ((!PVList.Number) && (!PadstackList.Number)) + return; + + if (IsFirst) { + /* the starting pin */ + pv = PVLIST_ENTRY(0); + PrintConnectionListEntry((char *) PCB_EMPTY(pv->Name), NULL, pcb_true, FP); + } + + /* we maybe have to start with i=1 if we are handling the + * starting-pin itself + */ + for (i = IsFirst ? 1 : 0; i < PVList.Number; i++) { + /* get the elements name or assume that its a via */ + pv = PVLIST_ENTRY(i); + PrintConnectionListEntry((char *) PCB_EMPTY(pv->Name), (pcb_element_t *) pv->Element, pcb_false, FP); + } + + for (i = IsFirst ? 1 : 0; i < PadstackList.Number; i++) { + pcb_subc_t *sc; + /* get the elements name or assume that its a via */ + ps = PADSTACKLIST_ENTRY(i); + if (ps->parent.data->parent_type == PCB_PARENT_SUBC) + sc = ps->parent.data->parent.subc; + else + sc = NULL; +#warning padstack TODO: get terminal name? PrintConnectionListEntry does not handle element! + sc = NULL; + PrintConnectionListEntry("TODO#termname", (pcb_element_t *)sc, pcb_false, FP); + } +} Index: tags/1.2.7/src/find_drc.c =================================================================== --- tags/1.2.7/src/find_drc.c (nonexistent) +++ tags/1.2.7/src/find_drc.c (revision 13657) @@ -0,0 +1,978 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "drc.h" +#include "compat_nls.h" + +#include "obj_arc_draw.h" +#include "obj_pad_draw.h" +#include "obj_rat_draw.h" +#include "obj_line_draw.h" +#include "obj_elem_draw.h" +#include "obj_poly_draw.h" +#include "obj_pinvia_draw.h" +#include "obj_pstk_draw.h" + +/* DRC related functions */ + +static void GotoError(void); +static pcb_bool DRCFind(int What, void *ptr1, void *ptr2, void *ptr3); + +static pcb_drc_violation_t + * pcb_drc_violation_new(const char *title, + const char *explanation, + pcb_coord_t x, pcb_coord_t y, + pcb_angle_t angle, + pcb_bool have_measured, + pcb_coord_t measured_value, + pcb_coord_t required_value, int object_count, long int *object_id_list, int *object_type_list) +{ + pcb_drc_violation_t *violation = (pcb_drc_violation_t *) malloc(sizeof(pcb_drc_violation_t)); + + violation->title = pcb_strdup(title); + violation->explanation = pcb_strdup(explanation); + violation->x = x; + violation->y = y; + violation->angle = angle; + violation->have_measured = have_measured; + violation->measured_value = measured_value; + violation->required_value = required_value; + violation->object_count = object_count; + violation->object_id_list = object_id_list; + violation->object_type_list = object_type_list; + + return violation; +} + +static void pcb_drc_violation_free(pcb_drc_violation_t * violation) +{ + free(violation->title); + free(violation->explanation); + free(violation); +} + +static gds_t drc_dialog_message; +static void reset_drc_dialog_message(void) +{ + gds_truncate(&drc_dialog_message, 0); + if (pcb_gui->drc_gui != NULL) + pcb_gui->drc_gui->reset_drc_dialog_message(); +} + +static void append_drc_dialog_message(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pcb_append_vprintf(&drc_dialog_message, fmt, ap); + va_end(ap); +} + +static void GotoError(void); + +/*---------------------------------------------------------------------------- + * Build a list of the of offending items by ID. (Currently just "thing") + */ +static void BuildObjectList(int *object_count, long int **object_id_list, int **object_type_list) +{ + *object_count = 0; + *object_id_list = NULL; + *object_type_list = NULL; + + switch (thing_type) { + case PCB_TYPE_LINE: + case PCB_TYPE_ARC: + case PCB_TYPE_POLY: + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + case PCB_TYPE_PSTK: + case PCB_TYPE_PAD: + case PCB_TYPE_ELEMENT: + case PCB_TYPE_RATLINE: + *object_count = 1; + *object_id_list = (long int *) malloc(sizeof(long int)); + *object_type_list = (int *) malloc(sizeof(int)); + **object_id_list = ((pcb_any_obj_t *) thing_ptr3)->ID; + **object_type_list = thing_type; + return; + + default: + fprintf(stderr, _("Internal error in BuildObjectList: unknown object type %i\n"), thing_type); + } +} + + + +/*---------------------------------------------------------------------------- + * Locate the coordinates of offending item (thing) + */ +static void LocateError(pcb_coord_t * x, pcb_coord_t * y) +{ + switch (thing_type) { + case PCB_TYPE_LINE: + { + pcb_line_t *line = (pcb_line_t *) thing_ptr3; + *x = (line->Point1.X + line->Point2.X) / 2; + *y = (line->Point1.Y + line->Point2.Y) / 2; + break; + } + case PCB_TYPE_ARC: + { + pcb_arc_t *arc = (pcb_arc_t *) thing_ptr3; + *x = arc->X; + *y = arc->Y; + break; + } + case PCB_TYPE_POLY: + { + pcb_poly_t *polygon = (pcb_poly_t *) thing_ptr3; + *x = (polygon->Clipped->contours->xmin + polygon->Clipped->contours->xmax) / 2; + *y = (polygon->Clipped->contours->ymin + polygon->Clipped->contours->ymax) / 2; + break; + } + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + { + pcb_pin_t *pin = (pcb_pin_t *) thing_ptr3; + *x = pin->X; + *y = pin->Y; + break; + } + case PCB_TYPE_PSTK: + { + pcb_pstk_t *ps = (pcb_pstk_t *) thing_ptr3; + *x = ps->x; + *y = ps->y; + break; + } + case PCB_TYPE_PAD: + { + pcb_pad_t *pad = (pcb_pad_t *) thing_ptr3; + *x = (pad->Point1.X + pad->Point2.X) / 2; + *y = (pad->Point1.Y + pad->Point2.Y) / 2; + break; + } + case PCB_TYPE_ELEMENT: + { + pcb_element_t *element = (pcb_element_t *) thing_ptr3; + *x = element->MarkX; + *y = element->MarkY; + break; + } + default: + return; + } +} + + +static void append_drc_violation(pcb_drc_violation_t * violation) +{ + if (pcb_gui->drc_gui != NULL) { + pcb_gui->drc_gui->append_drc_violation(violation); + } + else { + /* Fallback to formatting the violation message as text */ + append_drc_dialog_message("%s\n", violation->title); + append_drc_dialog_message(_("%m+near %$mD\n"), conf_core.editor.grid_unit->allow, violation->x, violation->y); + GotoError(); + } + + if (pcb_gui->drc_gui == NULL || pcb_gui->drc_gui->log_drc_violations) { + pcb_message(PCB_MSG_WARNING, _("WARNING! Design Rule error - %s\n"), violation->title); + pcb_message(PCB_MSG_WARNING, _("%m+near location %$mD\n"), conf_core.editor.grid_unit->allow, violation->x, violation->y); + } +} + + +/* + * message when asked about continuing DRC checks after next + * violation is found. + */ +#define DRC_CONTINUE _("Press Next to continue DRC checking") +#define DRC_NEXT _("Next") +#define DRC_CANCEL _("Cancel") + +static int throw_drc_dialog(void) +{ + int r; + + if (pcb_gui->drc_gui != NULL) { + r = pcb_gui->drc_gui->throw_drc_dialog(); + } + else { + /* Fallback to formatting the violation message as text */ + append_drc_dialog_message(DRC_CONTINUE); + r = pcb_gui->confirm_dialog(drc_dialog_message.array, DRC_CANCEL, DRC_NEXT); + reset_drc_dialog_message(); + } + return r; +} + +/* 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) +{ + const char *message; + pcb_coord_t x, y; + int object_count; + long int *object_id_list; + int *object_type_list; + pcb_drc_violation_t *violation; + + pcb_line_t *line = (pcb_line_t *) ptr2; + pcb_arc_t *arc = (pcb_arc_t *) ptr2; + pcb_pin_t *pin = (pcb_pin_t *) ptr2; + pcb_pad_t *pad = (pcb_pad_t *) ptr2; + pcb_pstk_t *ps = (pcb_pstk_t *) ptr2; + + thing_type = type; + thing_ptr1 = ptr1; + thing_ptr2 = ptr2; + thing_ptr3 = ptr2; + switch (type) { + case PCB_TYPE_LINE: + if (line->Clearance < 2 * PCB->Bloat) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, line); + message = _("Line with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + case PCB_TYPE_ARC: + if (arc->Clearance < 2 * PCB->Bloat) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, arc); + message = _("Arc with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + case PCB_TYPE_PAD: + if (pad->Clearance && pad->Clearance < 2 * PCB->Bloat) + if (pcb_is_pad_in_poly(pad, polygon)) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, pad); + message = _("Pad with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + case PCB_TYPE_PIN: + if (pin->Clearance && pin->Clearance < 2 * PCB->Bloat) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, pin); + message = _("Pin with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + case PCB_TYPE_VIA: + if (pin->Clearance && pin->Clearance < 2 * PCB->Bloat) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, pin); + message = _("Via with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + case PCB_TYPE_PSTK: + if (pcb_pstk_drc_check_clearance(ps, polygon, 2 * PCB->Bloat) != 0) { + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_SET(TheFlag, pin); + message = _("Padstack with insufficient clearance inside polygon\n"); + goto doIsBad; + } + break; + default: + pcb_message(PCB_MSG_ERROR, "hace: Bad Plow object in callback\n"); + } + return PCB_R_DIR_NOT_FOUND; + +doIsBad: + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_SET(PCB_FLAG_FOUND, polygon); + pcb_poly_invalidate_draw(layer, polygon); + pcb_draw_obj((pcb_any_obj_t *)ptr2); + drcerr_count++; + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(message, _("Circuits that are too close may bridge during imaging, etching,\n" "plating, or soldering processes resulting in a direct short."), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_false, /* MEASUREMENT OF ERROR UNKNOWN */ + 0, /* MAGNITUDE OF ERROR UNKNOWN */ + PCB->Bloat, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + return PCB_R_DIR_FOUND_CONTINUE; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_true); + return PCB_R_DIR_NOT_FOUND; +} + + + +/*----------------------------------------------------------------------------- + * Check for DRC violations + * see if the connectivity changes when everything is bloated, or shrunk + */ +int pcb_drc_all(void) +{ + pcb_coord_t x, y; + int object_count; + long int *object_id_list; + int *object_type_list; + pcb_drc_violation_t *violation; + int tmpcnt; + int nopastecnt = 0; + + reset_drc_dialog_message(); + + IsBad = pcb_false; + drcerr_count = 0; + pcb_layervis_save_stack(); + pcb_layervis_reset_stack(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + pcb_conn_lookup_init(); + + TheFlag = PCB_FLAG_FOUND | PCB_FLAG_DRC | PCB_FLAG_SELECTED; + + if (pcb_reset_conns(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + + User = pcb_false; + + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (!PCB_FLAG_TEST(PCB_FLAG_DRC, pin) + && DRCFind(PCB_TYPE_PIN, (void *) element, (void *) pin, (void *) pin)) { + IsBad = pcb_true; + break; + } + } + PCB_END_LOOP; + if (IsBad) + break; + PCB_PAD_LOOP(element); + { + + /* count up how many pads have no solderpaste openings */ + if (PCB_FLAG_TEST(PCB_FLAG_NOPASTE, pad)) + nopastecnt++; + + if (!PCB_FLAG_TEST(PCB_FLAG_DRC, pad) + && DRCFind(PCB_TYPE_PAD, (void *) element, (void *) pad, (void *) pad)) { + IsBad = pcb_true; + break; + } + } + PCB_END_LOOP; + if (IsBad) + break; + } + PCB_END_LOOP; + + if (!IsBad) + PCB_VIA_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_DRC, via) + && DRCFind(PCB_TYPE_VIA, (void *) via, (void *) via, (void *) via)) { + IsBad = pcb_true; + break; + } + } + PCB_END_LOOP; + + if (!IsBad) + PCB_PADSTACK_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_DRC, padstack) + && DRCFind(PCB_TYPE_PSTK, (void *) padstack, (void *) padstack, (void *) padstack)) { + IsBad = pcb_true; + break; + } + } + PCB_END_LOOP; + + TheFlag = (IsBad) ? PCB_FLAG_DRC : (PCB_FLAG_FOUND | PCB_FLAG_DRC | PCB_FLAG_SELECTED); + pcb_reset_conns(pcb_false); + TheFlag = PCB_FLAG_SELECTED; + /* check minimum widths and polygon clearances */ + if (!IsBad) { + PCB_LINE_COPPER_LOOP(PCB->Data); + { + /* check line clearances in polygons */ + pcb_poly_plows(PCB->Data, PCB_TYPE_LINE, layer, line, drc_callback); + if (IsBad) + break; + if (line->Thickness < PCB->minWid) { + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_SET(TheFlag, line); + pcb_line_invalidate_draw(layer, line); + drcerr_count++; + SetThing(PCB_TYPE_LINE, layer, line, line); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Line width is too thin"), _("Process specifications dictate a minimum feature-width\n" "that can reliably be reproduced"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + line->Thickness, PCB->minWid, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + } + PCB_ENDALL_LOOP; + } + if (!IsBad) { + PCB_ARC_COPPER_LOOP(PCB->Data); + { + pcb_poly_plows(PCB->Data, PCB_TYPE_ARC, layer, arc, drc_callback); + if (IsBad) + break; + if (arc->Thickness < PCB->minWid) { + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_SET(TheFlag, arc); + pcb_arc_invalidate_draw(layer, arc); + drcerr_count++; + SetThing(PCB_TYPE_ARC, layer, arc, arc); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Arc width is too thin"), _("Process specifications dictate a minimum feature-width\n" "that can reliably be reproduced"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + arc->Thickness, PCB->minWid, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + } + PCB_ENDALL_LOOP; + } + if (!IsBad) { + PCB_PIN_ALL_LOOP(PCB->Data); + { + pcb_poly_plows(PCB->Data, PCB_TYPE_PIN, element, pin, drc_callback); + if (IsBad) + break; + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) && pin->Thickness - pin->DrillingHole < 2 * PCB->minRing) { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_SET(TheFlag, pin); + pcb_pin_invalidate_draw(pin); + drcerr_count++; + SetThing(PCB_TYPE_PIN, element, pin, pin); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Pin annular ring too small"), _("Annular rings that are too small may erode during etching,\n" "resulting in a broken connection"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + (pin->Thickness - pin->DrillingHole) / 2, + PCB->minRing, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + if (pin->DrillingHole < PCB->minDrill) { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_SET(TheFlag, pin); + pcb_pin_invalidate_draw(pin); + drcerr_count++; + SetThing(PCB_TYPE_PIN, element, pin, pin); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Pin drill size is too small"), _("Process rules dictate the minimum drill size which can be used"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + pin->DrillingHole, PCB->minDrill, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + } + PCB_ENDALL_LOOP; + } + if (!IsBad) { + PCB_PAD_ALL_LOOP(PCB->Data); + { + pcb_poly_plows(PCB->Data, PCB_TYPE_PAD, element, pad, drc_callback); + if (IsBad) + break; + if (pad->Thickness < PCB->minWid) { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_SET(TheFlag, pad); + pcb_pad_invalidate_draw(pad); + drcerr_count++; + SetThing(PCB_TYPE_PAD, element, pad, pad); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Pad is too thin"), _("Pads which are too thin may erode during etching,\n" "resulting in a broken or unreliable connection"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + pad->Thickness, PCB->minWid, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + } + PCB_ENDALL_LOOP; + } + if (!IsBad) { + PCB_VIA_LOOP(PCB->Data); + { + pcb_poly_plows(PCB->Data, PCB_TYPE_VIA, via, via, drc_callback); + if (IsBad) + break; + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, via) && via->Thickness - via->DrillingHole < 2 * PCB->minRing) { + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_SET(TheFlag, via); + pcb_via_invalidate_draw(via); + drcerr_count++; + SetThing(PCB_TYPE_VIA, via, via, via); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Via annular ring too small"), _("Annular rings that are too small may erode during etching,\n" "resulting in a broken connection"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + (via->Thickness - via->DrillingHole) / 2, + PCB->minRing, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + if (via->DrillingHole < PCB->minDrill) { + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_SET(TheFlag, via); + pcb_via_invalidate_draw(via); + drcerr_count++; + SetThing(PCB_TYPE_VIA, via, via, via); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Via drill size is too small"), _("Process rules dictate the minimum drill size which can be used"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + via->DrillingHole, PCB->minDrill, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + pcb_undo_inc_serial(); + pcb_undo(pcb_false); + } + } + PCB_END_LOOP; + } + + if (!IsBad) { + PCB_PADSTACK_LOOP(PCB->Data); + { + pcb_coord_t ring = 0, hole = 0; + pcb_poly_plows(PCB->Data, PCB_TYPE_PSTK, padstack, padstack, drc_callback); + if (IsBad) + break; + pcb_pstk_drc_check_and_warn(padstack, &ring, &hole); + if ((ring > 0) || (hole > 0)) { + pcb_undo_add_obj_to_flag(padstack); + PCB_FLAG_SET(TheFlag, padstack); + pcb_pstk_invalidate_draw(padstack); + if (ring) { + drcerr_count++; + SetThing(PCB_TYPE_VIA, padstack, padstack, padstack); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("padstack annular ring too small"), _("Annular rings that are too small may erode during etching,\n" "resulting in a broken connection"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + ring, + PCB->minRing, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + } + if (hole > 0) { + drcerr_count++; + SetThing(PCB_TYPE_VIA, padstack, padstack, padstack); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Padstack drill size is too small"), _("Process rules dictate the minimum drill size which can be used"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + hole, PCB->minDrill, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + } + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + } + } + PCB_END_LOOP; + } + + pcb_conn_lookup_uninit(); + TheFlag = PCB_FLAG_FOUND; + Bloat = 0; + + /* check silkscreen minimum widths outside of elements */ + /* XXX - need to check text and polygons too! */ + TheFlag = PCB_FLAG_SELECTED; + if (!IsBad) { + PCB_LINE_SILK_LOOP(PCB->Data); + { + if (line->Thickness < PCB->minSlk) { + PCB_FLAG_SET(TheFlag, line); + pcb_line_invalidate_draw(layer, line); + drcerr_count++; + SetThing(PCB_TYPE_LINE, layer, line, line); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Silk line is too thin"), _("Process specifications dictate a minimum silkscreen feature-width\n" "that can reliably be reproduced"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + line->Thickness, PCB->minSlk, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + } + } + PCB_ENDALL_LOOP; + } + + /* check silkscreen minimum widths inside of elements */ + /* XXX - need to check text and polygons too! */ + TheFlag = PCB_FLAG_SELECTED; + if (!IsBad) { + PCB_ELEMENT_LOOP(PCB->Data); + { + tmpcnt = 0; + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + if (line->Thickness < PCB->minSlk) + tmpcnt++; + } + PCB_END_LOOP; + if (tmpcnt > 0) { + const char *title; + const char *name; + char *buffer; + int buflen; + + PCB_FLAG_SET(TheFlag, element); + pcb_elem_invalidate_draw(element); + drcerr_count++; + SetThing(PCB_TYPE_ELEMENT, element, element, element); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + + title = _("Element %s has %i silk lines which are too thin"); + name = PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)); + + /* -4 is for the %s and %i place-holders */ + /* +11 is the max printed length for a 32 bit integer */ + /* +1 is for the \0 termination */ + buflen = strlen(title) - 4 + strlen(name) + 11 + 1; + buffer = (char *) malloc(buflen); + pcb_snprintf(buffer, buflen, title, name, tmpcnt); + + violation = pcb_drc_violation_new(buffer, _("Process specifications dictate a minimum silkscreen\n" "feature-width that can reliably be reproduced"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + 0, /* MINIMUM OFFENDING WIDTH UNKNOWN */ + PCB->minSlk, object_count, object_id_list, object_type_list); + free(buffer); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + } + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(PCB->Data); + { + int n; + + tmpcnt = 0; + for(n = 0; n < subc->data->LayerN; n++) { + pcb_layer_type_t lyt = pcb_layer_flags_(&subc->data->Layer[n]); + if ((lyt & PCB_LYT_SILK) == 0) + continue; + PCB_LINE_LOOP(&subc->data->Layer[n]); + { + if (line->Thickness < PCB->minSlk) { + PCB_FLAG_SET(TheFlag, line); + tmpcnt++; + } + } + PCB_END_LOOP; + PCB_ARC_LOOP(&subc->data->Layer[n]); + { + if (arc->Thickness < PCB->minSlk) { + PCB_FLAG_SET(TheFlag, arc); + tmpcnt++; + } + } + PCB_END_LOOP; + } + + if (tmpcnt > 0) { + const char *title; + const char *name; + char *buffer; + + PCB_FLAG_SET(TheFlag, subc); + DrawSubc(subc); + drcerr_count++; + SetThing(PCB_TYPE_SUBC, subc, subc, subc); + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + + title = _("Subcircuit %s has %i silk lines which are too thin"); + name = PCB_UNKNOWN(subc->refdes); + buffer = pcb_strdup_printf(title, name, tmpcnt); + + violation = pcb_drc_violation_new(buffer, _("Process specifications dictate a minimum silkscreen\n" "feature-width that can reliably be reproduced"), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_true, /* MEASUREMENT OF ERROR KNOWN */ + 0, /* MINIMUM OFFENDING WIDTH UNKNOWN */ + PCB->minSlk, object_count, object_id_list, object_type_list); + free(buffer); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + if (!throw_drc_dialog()) { + IsBad = pcb_true; + break; + } + } + } + PCB_END_LOOP; + + } + + + if (IsBad) { + pcb_undo_inc_serial(); + } + + + pcb_layervis_restore_stack(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + pcb_gui->invalidate_all(); + + if (nopastecnt > 0) { + pcb_message(PCB_MSG_WARNING, _("Warning: %d pad%s the nopaste flag set.\n"), nopastecnt, nopastecnt > 1 ? "s have" : " has"); + } + return IsBad ? -drcerr_count : drcerr_count; +} + + + +/*----------------------------------------------------------------------------- + * 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(int What, void *ptr1, void *ptr2, void *ptr3) +{ + pcb_coord_t x, y; + int object_count; + long int *object_id_list; + int *object_type_list; + pcb_drc_violation_t *violation; + + if (PCB->Shrink != 0) { + Bloat = -PCB->Shrink; + TheFlag = PCB_FLAG_DRC | PCB_FLAG_SELECTED; + ListStart(ptr2); + DoIt(pcb_true, pcb_false); + /* ok now the shrunk net has the PCB_FLAG_SELECTED set */ + DumpList(); + TheFlag = PCB_FLAG_FOUND; + ListStart(ptr2); + Bloat = 0; + drc = pcb_true; /* abort the search if we find anything not already found */ + if (DoIt(pcb_true, pcb_false)) { + DumpList(); + /* make the flag changes undoable */ + TheFlag = PCB_FLAG_FOUND | PCB_FLAG_SELECTED; + pcb_reset_conns(pcb_false); + User = pcb_true; + drc = pcb_false; + Bloat = -PCB->Shrink; + TheFlag = PCB_FLAG_SELECTED; + ListStart(ptr2); + DoIt(pcb_true, pcb_true); + DumpList(); + ListStart(ptr2); + TheFlag = PCB_FLAG_FOUND; + Bloat = 0; + drc = pcb_true; + DoIt(pcb_true, pcb_true); + DumpList(); + User = pcb_false; + drc = pcb_false; + drcerr_count++; + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Potential for broken trace"), _("Insufficient overlap between objects can lead to broken tracks\n" "due to registration errors with old wheel style photo-plotters."), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_false, /* MEASUREMENT OF ERROR UNKNOWN */ + 0, /* MAGNITUDE OF ERROR UNKNOWN */ + PCB->Shrink, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + + if (!throw_drc_dialog()) + return (pcb_true); + pcb_undo_inc_serial(); + pcb_undo(pcb_true); + } + DumpList(); + } + /* now check the bloated condition */ + drc = pcb_false; + pcb_reset_conns(pcb_false); + TheFlag = PCB_FLAG_FOUND; + ListStart(ptr2); + Bloat = PCB->Bloat; + drc = pcb_true; + while (DoIt(pcb_true, pcb_false)) { + DumpList(); + /* make the flag changes undoable */ + TheFlag = PCB_FLAG_FOUND | PCB_FLAG_SELECTED; + pcb_reset_conns(pcb_false); + User = pcb_true; + drc = pcb_false; + Bloat = 0; + TheFlag = PCB_FLAG_SELECTED; + ListStart(ptr2); + DoIt(pcb_true, pcb_true); + DumpList(); + TheFlag = PCB_FLAG_FOUND; + ListStart(ptr2); + Bloat = PCB->Bloat; + drc = pcb_true; + DoIt(pcb_true, pcb_true); + DumpList(); + drcerr_count++; + LocateError(&x, &y); + BuildObjectList(&object_count, &object_id_list, &object_type_list); + violation = pcb_drc_violation_new(_("Copper areas too close"), _("Circuits that are too close may bridge during imaging, etching,\n" "plating, or soldering processes resulting in a direct short."), x, y, 0, /* ANGLE OF ERROR UNKNOWN */ + pcb_false, /* MEASUREMENT OF ERROR UNKNOWN */ + 0, /* MAGNITUDE OF ERROR UNKNOWN */ + PCB->Bloat, object_count, object_id_list, object_type_list); + append_drc_violation(violation); + pcb_drc_violation_free(violation); + free(object_id_list); + free(object_type_list); + User = pcb_false; + drc = pcb_false; + if (!throw_drc_dialog()) + return (pcb_true); + pcb_undo_inc_serial(); + pcb_undo(pcb_true); + /* highlight the rest of the encroaching net so it's not reported again */ + TheFlag |= PCB_FLAG_SELECTED; + Bloat = 0; + ListStart(thing_ptr2); + DoIt(pcb_true, pcb_true); + DumpList(); + drc = pcb_true; + Bloat = PCB->Bloat; + ListStart(ptr2); + } + drc = pcb_false; + DumpList(); + TheFlag = PCB_FLAG_FOUND | PCB_FLAG_SELECTED; + pcb_reset_conns(pcb_false); + return (pcb_false); +} + +/*---------------------------------------------------------------------------- + * center the display to show the offending item (thing) + */ +static void GotoError(void) +{ + pcb_coord_t X, Y; + + LocateError(&X, &Y); + + switch (thing_type) { + case PCB_TYPE_LINE: + case PCB_TYPE_ARC: + case PCB_TYPE_POLY: + pcb_layervis_change_group_vis(pcb_layer_id(PCB->Data, (pcb_layer_t *) thing_ptr1), pcb_true, pcb_true); + } + pcb_center_display(X, Y); +} Index: tags/1.2.7/src/find_geo.c =================================================================== --- tags/1.2.7/src/find_geo.c (nonexistent) +++ tags/1.2.7/src/find_geo.c (revision 13657) @@ -0,0 +1,949 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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_intersect_line_line()' + */ + +#include "macro.h" +#include "obj_arc_ui.h" +#include "obj_pstk_inlines.h" + +#define EXPAND_BOUNDS(p) if (Bloat > 0) {\ + (p)->BoundingBox.X1 -= Bloat; \ + (p)->BoundingBox.X2 += Bloat; \ + (p)->BoundingBox.Y1 -= Bloat; \ + (p)->BoundingBox.Y2 += Bloat;} + +#define IS_PV_ON_RAT(PV, Rat) \ + (pcb_is_point_on_line_end((PV)->X,(PV)->Y, (Rat))) + +#define IS_PV_ON_ARC(PV, Arc) \ + (PCB_FLAG_TEST(PCB_FLAG_SQUARE, (PV)) ? \ + pcb_is_arc_in_rectangle( \ + (PV)->X -MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y -MAX(((PV)->Thickness+1)/2 +Bloat,0), \ + (PV)->X +MAX(((PV)->Thickness+1)/2 +Bloat,0), (PV)->Y +MAX(((PV)->Thickness+1)/2 +Bloat,0), \ + (Arc)) : \ + pcb_is_point_on_arc((PV)->X,(PV)->Y,MAX((PV)->Thickness/2.0 + Bloat,0.0), (Arc))) + +#define IS_PV_ON_PAD(PV,Pad) \ + ( pcb_is_point_in_pad((PV)->X, (PV)->Y, MAX((PV)->Thickness/2 +Bloat,0), (Pad))) + +/* 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 ArcArcIntersect(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 IsRatPointOnLineSpec(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 if point is same as arc end point or center point + */ +static pcb_bool IsRatPointOnArcSpec(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 if rat line point is connected to a polygon + */ +static pcb_bool IsRatPointOnPoly(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; +} + +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_intersect_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_intersect_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_pad(Line2->Point1.X, Line2->Point1.Y, MAX(Line2->Thickness / 2 + Bloat, 0), (pcb_pad_t *) Line1) + || pcb_is_point_in_pad(Line2->Point2.X, Line2->Point2.Y, MAX(Line2->Thickness / 2 + Bloat, 0), (pcb_pad_t *) Line1) + || pcb_is_point_in_pad(Line1->Point1.X, Line1->Point1.Y, MAX(Line1->Thickness / 2 + Bloat, 0), (pcb_pad_t *) Line2) + || pcb_is_point_in_pad(Line1->Point2.X, Line1->Point2.Y, MAX(Line1->Thickness / 2 + Bloat, 0), (pcb_pad_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_pad() 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_intersect_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_pad(ex, ey, Arc->Thickness * 0.5 + Bloat, (pcb_pad_t *) Line)) + return pcb_true; + + pcb_arc_get_end(Arc, 1, &ex, &ey); + if (pcb_is_point_in_pad(ex, ey, Arc->Thickness * 0.5 + Bloat, (pcb_pad_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_is_arc_in_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_is_arc_in_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_is_line_in_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 pad connects to a non-clearing polygon + * + * The polygon is assumed to already have been proven non-clearing + */ +pcb_bool pcb_is_pad_in_poly(pcb_pad_t *pad, pcb_poly_t *polygon) +{ + return pcb_is_line_in_poly((pcb_line_t *) pad, polygon); +} + +/* --------------------------------------------------------------------------- + * 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_is_poly_in_poly(pcb_poly_t *P1, pcb_poly_t *P2) +{ + 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; + + /* 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_is_line_in_poly(&line, P2)) + return (pcb_true); + line.Point1.X = line.Point2.X; + line.Point1.Y = line.Point2.Y; + } + } + } + } + + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * some of the 'pad' routines are the same as for lines because the 'pad' + * struct starts with a line struct. See global.h for details + */ +pcb_bool pcb_intersect_line_pad(pcb_line_t *Line, pcb_pad_t *Pad) +{ + return pcb_intersect_line_line((Line), (pcb_line_t *) Pad); +} + +pcb_bool pcb_intersect_arc_pad(pcb_arc_t *Arc, pcb_pad_t *Pad) +{ + return pcb_intersect_line_arc((pcb_line_t *) (Pad), (Arc)); +} + +pcb_bool BoxBoxIntersection(pcb_box_t *b1, pcb_box_t *b2) +{ + if (b2->X2 < b1->X1 || b2->X1 > b1->X2) + return pcb_false; + if (b2->Y2 < b1->Y1 || b2->Y1 > b1->Y2) + return pcb_false; + return pcb_true; +} + +static pcb_bool PadPadIntersect(pcb_pad_t *p1, pcb_pad_t *p2) +{ + return pcb_intersect_line_pad((pcb_line_t *) p1, p2); +} + +static inline pcb_bool PV_TOUCH_PV(pcb_pin_t *PV1, pcb_pin_t *PV2) +{ + double t1, t2; + pcb_box_t b1, b2; + int shape1, shape2; + + shape1 = PCB_FLAG_SQUARE_GET(PV1); + shape2 = PCB_FLAG_SQUARE_GET(PV2); + + if ((shape1 > 1) || (shape2 > 1)) { + pcb_polyarea_t *pl1, *pl2; + int ret; + + pl1 = pcb_poly_from_pin(PV1, PIN_SIZE(PV1) + Bloat, 0); + pl2 = pcb_poly_from_pin(PV2, PIN_SIZE(PV2) + Bloat, 0); + ret = pcb_polyarea_touching(pl1, pl2); + pcb_polyarea_free(&pl1); + pcb_polyarea_free(&pl2); + return ret; + } + + + t1 = MAX(PV1->Thickness / 2.0 + Bloat, 0); + t2 = MAX(PV2->Thickness / 2.0 + Bloat, 0); + if (pcb_is_point_in_pin(PV1->X, PV1->Y, t1, PV2) + || pcb_is_point_in_pin(PV2->X, PV2->Y, t2, PV1)) + return pcb_true; + if (!PCB_FLAG_TEST(PCB_FLAG_SQUARE, PV1) || !PCB_FLAG_TEST(PCB_FLAG_SQUARE, PV2)) + return pcb_false; + /* check for square/square overlap */ + b1.X1 = PV1->X - t1; + b1.X2 = PV1->X + t1; + b1.Y1 = PV1->Y - t1; + b1.Y2 = PV1->Y + t1; + t2 = PV2->Thickness / 2.0; + b2.X1 = PV2->X - t2; + b2.X2 = PV2->X + t2; + b2.Y1 = PV2->Y - t2; + b2.Y2 = PV2->Y + t2; + return BoxBoxIntersection(&b1, &b2); +} + +pcb_bool pcb_intersect_line_pin(pcb_pin_t *PV, pcb_line_t *Line) +{ + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, PV)) { + int shape = PCB_FLAG_SQUARE_GET(PV); + if (shape <= 1) { + /* the original square case */ + /* IsLineInRectangle already has Bloat factor */ + return pcb_is_line_in_rectangle(PV->X - (PIN_SIZE(PV) + 1) / 2, + PV->Y - (PIN_SIZE(PV) + 1) / 2, + PV->X + (PIN_SIZE(PV) + 1) / 2, PV->Y + (PIN_SIZE(PV) + 1) / 2, Line); + } + + { + /* shaped pin case */ + pcb_polyarea_t *pl, *lp; + int ret; + + pl = pcb_poly_from_pin(PV, PIN_SIZE(PV), 0); + lp = pcb_poly_from_line(Line, Line->Thickness + Bloat); + ret = pcb_polyarea_touching(lp, pl); + pcb_polyarea_free(&pl); + pcb_polyarea_free(&lp); + return ret; + } + + } + + /* the original round pin version */ + return pcb_is_point_in_pad(PV->X, PV->Y, MAX(PIN_SIZE(PV) / 2.0 + Bloat, 0.0), (pcb_pad_t *) Line); +} + +/* returns whether a round-cap pcb line touches a polygon; assumes bounding + boxes do touch */ +PCB_INLINE pcb_bool_t pcb_intersect_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; + double dx, dy, h; + + /* 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; + h = 0.5 * thick / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + ox = dy * h + 0.5 * SGN(dy); + oy = -(dx * h + 0.5 * SGN(dx)); + + /* long line - consider edge intersection */ + if (pcb_pline_isect_line(pl, x1 + ox, y1 + oy, x2 + ox, y2 + oy)) return pcb_true; + if (pcb_pline_isect_line(pl, x1 - ox, y1 - oy, x2 - ox, y2 - oy)) 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(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_INLINE pcb_bool_t pcb_pstk_intersect_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_intersect_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(shape->data.line, tmp); + return pcb_intersect_line_line(line, &tmp); + } + case PCB_PSSH_CIRC: + { + pcb_pad_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_pad(shape->data.circ.x + ps->x, shape->data.circ.y + ps->y, shape->data.circ.dia/2, &tmp); + } + } + return pcb_false; +} + + +PCB_INLINE pcb_bool_t pcb_pstk_intersect_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_is_arc_in_polyarea(&tmp, shape->data.poly.pa); + } + + case PCB_PSSH_LINE: + { + pcb_line_t tmp; + shape_line_to_pcb_line(shape->data.line, tmp); + return pcb_intersect_line_arc(&tmp, arc); + } + case PCB_PSSH_CIRC: + pcb_is_point_on_arc(shape->data.circ.x + ps->x, shape->data.circ.y + ps->x, shape->data.circ.dia/2, arc); + break; + } + return pcb_false; +} + +PCB_INLINE pcb_bool_t pcb_pstk_intersect_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_polyarea_t *shp = pcb_polyarea_create(); + pcb_pline_t *pl; + pcb_vector_t v; + pcb_bool res; + int n; + + 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); + 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(shape->data.line, tmp); + pcb_line_bbox(&tmp); + return pcb_is_line_in_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_is_line_in_poly(&tmp, poly); + } + } + return pcb_false; + +} + +PCB_INLINE pcb_bool_t pcb_pstk_intersect_rat(pcb_pstk_t *ps, pcb_rat_t *rat) +{ + return ((rat->Point1.X == ps->x) && (rat->Point1.Y == ps->y)) || ((rat->Point2.X == ps->x) && (rat->Point2.Y == ps->y)); +} Index: tags/1.2.7/src/find_intconn.c =================================================================== --- tags/1.2.7/src/find_intconn.c (nonexistent) +++ tags/1.2.7/src/find_intconn.c (revision 13657) @@ -0,0 +1,133 @@ +/* + * + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996, 2005 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Contact addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +void LOC_int_conn_element(pcb_element_t *e, int ic, int from_type, void *from_ptr) +{ +/* int tlayer = -1;*/ + + /* Internal connection: if pins/pads in the same element have the same + internal connection group number, they are connected */ + PCB_PIN_LOOP(e); + { + if ((from_ptr != pin) && (ic == pin->intconn)) { + if (!PCB_FLAG_TEST(TheFlag, pin)) + ADD_PV_TO_LIST(pin, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_END_LOOP; + +/* + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + if (layer == PCB_COMPONENT_SIDE) + tlayer = PCB_COMPONENT_SIDE; + else if (layer == PCB_SOLDER_SIDE) + tlayer = PCB_SOLDER_SIDE; + } +*/ + +/* if (tlayer >= 0)*/ { + PCB_PAD_LOOP(e); + { + if ((from_ptr != pad) && (ic == pad->intconn)) { + int padlayer = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE; + if ((!PCB_FLAG_TEST(TheFlag, pad)) /* && (tlayer != padlayer)*/) { + ADD_PAD_TO_LIST(padlayer, pad, from_type, from_ptr, PCB_FCT_INTERNAL); +/* if (LookupLOConnectionsToPad(pad, LayerGroup)) + retv = pcb_true;*/ + } + } + } + PCB_END_LOOP; + } +} + +static void LOC_int_conn_subc(pcb_subc_t *s, int ic, int from_type, void *from_ptr) +{ + if (s == NULL) + return; + + PCB_VIA_LOOP(s->data); + { + if ((via != from_ptr) && (via->term != NULL) && (via->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, via))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, via); + ADD_PV_TO_LIST(via, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_END_LOOP; + + PCB_PADSTACK_LOOP(s->data); + { + if ((padstack != from_ptr) && (padstack->term != NULL) && (padstack->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, padstack))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, padstack); + ADD_PADSTACK_TO_LIST(padstack, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_END_LOOP; + + PCB_LINE_COPPER_LOOP(s->data); + { + if ((line != from_ptr) && (line->term != NULL) && (line->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, line))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, line); + ADD_LINE_TO_LIST(l, line, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_ENDALL_LOOP; + + PCB_ARC_COPPER_LOOP(s->data); + { + if ((arc != from_ptr) && (arc->term != NULL) && (arc->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, arc))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, arc); + ADD_ARC_TO_LIST(l, arc, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_ENDALL_LOOP; + + PCB_POLY_COPPER_LOOP(s->data); + { + if ((polygon != from_ptr) && (polygon->term != NULL) && (polygon->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, polygon))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, polygon); + ADD_POLYGON_TO_LIST(l, polygon, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_ENDALL_LOOP; + +#warning subc TODO +#if 0 +no find through text yet + PCB_TEXT_COPPER_LOOP(s->data); + { + if ((text != from_ptr) && (text->term != NULL) && (text->intconn == ic) && (!PCB_FLAG_TEST(TheFlag, text))) { + PCB_FLAG_SET(PCB_FLAG_DRC_INTCONN, text); + ADD_TEXT_TO_LIST(l, text, from_type, from_ptr, PCB_FCT_INTERNAL); + } + } + PCB_ENDALL_LOOP; +#endif +} Index: tags/1.2.7/src/find_lookup.c =================================================================== --- tags/1.2.7/src/find_lookup.c (nonexistent) +++ tags/1.2.7/src/find_lookup.c (revision 13657) @@ -0,0 +1,1712 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "compat_nls.h" +#include "board.h" +#include "obj_subc_parent.h" + +static inline pcb_r_dir_t r_search_pt(pcb_rtree_t * rtree, const pcb_point_t * pt, + int radius, + 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_box_t box; + + box.X1 = pt->X - radius; + box.X2 = pt->X + radius; + box.Y1 = pt->Y - radius; + box.Y2 = pt->Y + radius; + + return pcb_r_search(rtree, &box, region_in_search, rectangle_in_region, closure, num_found); +} + + +/* Connection lookup functions */ + +static pcb_bool ADD_PV_TO_LIST(pcb_pin_t *Pin, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (User) + pcb_undo_add_obj_to_flag(Pin); + PCB_FLAG_SET(TheFlag, Pin); + make_callback(PCB_TYPE_PIN, Pin, from_type, from_ptr, type); + PVLIST_ENTRY(PVList.Number) = Pin; + PVList.Number++; +#ifdef DEBUG + if (PVList.Number > PVList.Size) + printf("ADD_PV_TO_LIST overflow! num=%d size=%d\n", PVList.Number, PVList.Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, Pin)) + return (SetThing(PCB_TYPE_PIN, Pin->Element, Pin, Pin)); + return pcb_false; +} + +static pcb_bool ADD_PS_TO_LIST(pcb_pstk_t *ps, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (User) + pcb_undo_add_obj_to_flag(ps); + PCB_FLAG_SET(TheFlag, ps); + make_callback(PCB_TYPE_PSTK, ps, from_type, from_ptr, type); + PADSTACKLIST_ENTRY(PadstackList.Number) = ps; + PadstackList.Number++; +#ifdef DEBUG + if (PadstackList.Number > PadstackList.Size) + printf("ADD_PS_TO_LIST overflow! num=%d size=%d\n", PadstackList.Number, PadstackList.Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps)) { +#warning padstack TODO: this NULL should have been ps->Element + return (SetThing(PCB_TYPE_PSTK, NULL, ps, ps)); + } + return pcb_false; +} + +static pcb_bool ADD_PADSTACK_TO_LIST(pcb_pstk_t *ps, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (User) + pcb_undo_add_obj_to_flag(ps); + PCB_FLAG_SET(TheFlag, ps); + make_callback(PCB_TYPE_PSTK, ps, from_type, from_ptr, type); + PADSTACKLIST_ENTRY(PVList.Number) = ps; + PadstackList.Number++; +#ifdef DEBUG + if (PVList.Number > PVList.Size) + printf("ADD_PADSTACK_TO_LIST overflow! num=%d size=%d\n", PVList.Number, PVList.Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, ps) && (ps->parent.data->parent_type == PCB_PARENT_SUBC)) + return (SetThing(PCB_TYPE_PSTK, ps->parent.data->parent.subc, ps, ps)); + return pcb_false; +} + +static pcb_bool ADD_PAD_TO_LIST(pcb_cardinal_t L, pcb_pad_t *Pad, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (PadList[L].Data == NULL) + return pcb_false; + +/*fprintf(stderr, "ADD_PAD_TO_LIST cardinal %d %p %d\n", L, Pad, from_type);*/ + if (User) + pcb_undo_add_obj_to_flag(Pad); + PCB_FLAG_SET(TheFlag, Pad); + make_callback(PCB_TYPE_PAD, Pad, from_type, from_ptr, type); + PADLIST_ENTRY((L), PadList[(L)].Number) = Pad; + PadList[(L)].Number++; +#ifdef DEBUG + if (PadList[(L)].Number > PadList[(L)].Size) + printf("ADD_PAD_TO_LIST overflow! lay=%d, num=%d size=%d\n", L, PadList[(L)].Number, PadList[(L)].Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, Pad)) + return (SetThing(PCB_TYPE_PAD, Pad->Element, Pad, Pad)); + return pcb_false; +} + +static pcb_bool ADD_LINE_TO_LIST(pcb_layer_id_t L, pcb_line_t *Ptr, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (LineList[L].Data == NULL) + return pcb_false; + if (User) + pcb_undo_add_obj_to_flag(Ptr); + PCB_FLAG_SET(TheFlag, (Ptr)); + make_callback(PCB_TYPE_LINE, Ptr, from_type, from_ptr, type); + LINELIST_ENTRY((L), LineList[(L)].Number) = (Ptr); + LineList[(L)].Number++; +#ifdef DEBUG + if (LineList[(L)].Number > LineList[(L)].Size) + printf("ADD_LINE_TO_LIST overflow! lay=%d, num=%d size=%d\n", L, LineList[(L)].Number, LineList[(L)].Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, (Ptr))) + return (SetThing(PCB_TYPE_LINE, LAYER_PTR(L), (Ptr), (Ptr))); + return pcb_false; +} + +static pcb_bool ADD_ARC_TO_LIST(pcb_cardinal_t L, pcb_arc_t *Ptr, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (ArcList[L].Data == NULL) + return pcb_false; + + if (User) + pcb_undo_add_obj_to_flag(Ptr); + PCB_FLAG_SET(TheFlag, (Ptr)); + make_callback(PCB_TYPE_ARC, Ptr, from_type, from_ptr, type); + ARCLIST_ENTRY((L), ArcList[(L)].Number) = (Ptr); + ArcList[(L)].Number++; +#ifdef DEBUG + if (ArcList[(L)].Number > ArcList[(L)].Size) + printf("ADD_ARC_TO_LIST overflow! lay=%d, num=%d size=%d\n", L, ArcList[(L)].Number, ArcList[(L)].Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, (Ptr))) + return (SetThing(PCB_TYPE_ARC, LAYER_PTR(L), (Ptr), (Ptr))); + return pcb_false; +} + +static pcb_bool ADD_RAT_TO_LIST(pcb_rat_t *Ptr, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (User) + pcb_undo_add_obj_to_flag(Ptr); + PCB_FLAG_SET(TheFlag, (Ptr)); + make_callback(PCB_TYPE_RATLINE, Ptr, from_type, from_ptr, type); + RATLIST_ENTRY(RatList.Number) = (Ptr); + RatList.Number++; +#ifdef DEBUG + if (RatList.Number > RatList.Size) + printf("ADD_RAT_TO_LIST overflow! num=%d size=%d\n", RatList.Number, RatList.Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, (Ptr))) + return (SetThing(PCB_TYPE_RATLINE, (Ptr), (Ptr), (Ptr))); + return pcb_false; +} + +static pcb_bool ADD_POLYGON_TO_LIST(pcb_cardinal_t L, pcb_poly_t *Ptr, int from_type, void *from_ptr, pcb_found_conn_type_t type) +{ + if (PolygonList[L].Data == NULL) + return pcb_false; + + if (User) + pcb_undo_add_obj_to_flag(Ptr); + PCB_FLAG_SET(TheFlag, (Ptr)); + make_callback(PCB_TYPE_POLY, Ptr, from_type, from_ptr, type); + POLYGONLIST_ENTRY((L), PolygonList[(L)].Number) = (Ptr); + PolygonList[(L)].Number++; +#ifdef DEBUG + if (PolygonList[(L)].Number > PolygonList[(L)].Size) + printf("ADD_ARC_TO_LIST overflow! lay=%d, num=%d size=%d\n", L, PolygonList[(L)].Number, PolygonList[(L)].Size); +#endif + if (drc && !PCB_FLAG_TEST(PCB_FLAG_SELECTED, (Ptr))) + return (SetThing(PCB_TYPE_POLY, LAYER_PTR(L), (Ptr), (Ptr))); + return pcb_false; +} + +pcb_bool SetThing(int type, void *ptr1, void *ptr2, void *ptr3) +{ + thing_ptr1 = ptr1; + thing_ptr2 = ptr2; + thing_ptr3 = ptr3; + thing_type = type; + if (type == PCB_TYPE_PIN && ptr1 == NULL) { + thing_ptr1 = ptr3; + thing_type = PCB_TYPE_VIA; + } + return pcb_true; +} + +#include "find_intconn.c" + +/* --------------------------------------------------------------------------- + * releases all allocated memory + */ +void pcb_layout_lookup_uninit(void) +{ + pcb_cardinal_t i; + + for (i = 0; i < pcb_max_layer; i++) { + free(LineList[i].Data); + LineList[i].Data = NULL; + free(ArcList[i].Data); + ArcList[i].Data = NULL; + free(PolygonList[i].Data); + PolygonList[i].Data = NULL; + } + free(PVList.Data); + PVList.Data = NULL; + free(PadstackList.Data); + PadstackList.Data = NULL; + free(RatList.Data); + RatList.Data = NULL; +} + +void pcb_component_lookup_uninit(void) +{ +/*fprintf(stderr, "PadList free both\n");*/ + free(PadList[0].Data); + PadList[0].Data = NULL; + free(PadList[1].Data); + PadList[1].Data = NULL; +} + +/* --------------------------------------------------------------------------- + * allocates memory for component related stacks ... + * initializes index and sorts it by X1 and X2 + */ +void pcb_component_lookup_init(void) +{ + pcb_cardinal_t i; + + /* initialize pad data; start by counting the total number + * on each of the two possible layers + */ + NumberOfPads[PCB_COMPONENT_SIDE] = NumberOfPads[PCB_SOLDER_SIDE] = 0; + PCB_PAD_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad)) + NumberOfPads[PCB_SOLDER_SIDE]++; + else + NumberOfPads[PCB_COMPONENT_SIDE]++; + } + PCB_ENDALL_LOOP; + for (i = 0; i < 2; i++) { +/*fprintf(stderr, "PadList alloc %d: %d\n", i, NumberOfPads[i]);*/ + + /* allocate memory for working list */ + PadList[i].Data = (void **) calloc(NumberOfPads[i], sizeof(pcb_pad_t *)); + + /* clear some struct members */ + PadList[i].Location = 0; + PadList[i].DrawLocation = 0; + PadList[i].Number = 0; + PadList[i].Size = NumberOfPads[i]; + } +} + +/* --------------------------------------------------------------------------- + * allocates memory for component related stacks ... + * initializes index and sorts it by X1 and X2 + */ +void pcb_layout_lookup_init(void) +{ + pcb_layer_id_t i; + + /* initialize line arc and polygon data */ + for(i = 0; i < pcb_max_layer; i++) { + pcb_layer_t *layer = LAYER_PTR(i); + + if (pcb_layer_flags(PCB, i) & PCB_LYT_COPPER) { + + if ((layer->line_tree != NULL) && (layer->line_tree->size > 0)) { + LineList[i].Size = layer->line_tree->size; + LineList[i].Data = (void **) calloc(LineList[i].Size, sizeof(pcb_line_t *)); + } + if ((layer->arc_tree != NULL) && (layer->arc_tree->size > 0)) { + ArcList[i].Size = layer->arc_tree->size; + ArcList[i].Data = (void **) calloc(ArcList[i].Size, sizeof(pcb_arc_t *)); + } + if ((layer->polygon_tree != NULL) && (layer->polygon_tree->size > 0)) { + PolygonList[i].Size = layer->polygon_tree->size; + PolygonList[i].Data = (void **) calloc(PolygonList[i].Size, sizeof(pcb_poly_t *)); + } + + } + + /* clear some struct members */ + LineList[i].Location = 0; + LineList[i].DrawLocation = 0; + LineList[i].Number = 0; + ArcList[i].Location = 0; + ArcList[i].DrawLocation = 0; + ArcList[i].Number = 0; + PolygonList[i].Location = 0; + PolygonList[i].DrawLocation = 0; + PolygonList[i].Number = 0; + } + + if (PCB->Data->pin_tree) + TotalP = PCB->Data->pin_tree->size; + else + TotalP = 0; + if (PCB->Data->via_tree) + TotalV = PCB->Data->via_tree->size; + else + TotalV = 0; + if (PCB->Data->padstack_tree) + TotalPs = PCB->Data->padstack_tree->size; + else + TotalPs = 0; + /* allocate memory for 'new PV to check' list and clear struct */ + PVList.Data = (void **) calloc(TotalP + TotalV, sizeof(pcb_pin_t *)); + PVList.Size = TotalP + TotalV; + PVList.Location = 0; + PVList.DrawLocation = 0; + PVList.Number = 0; + /* allocate memory for 'new padstack to check' list and clear struct */ + PadstackList.Data = (void **) calloc(TotalPs, sizeof(pcb_pstk_t *)); + PadstackList.Size = TotalPs; + PadstackList.Location = 0; + PadstackList.DrawLocation = 0; + PadstackList.Number = 0; + /* Initialize ratline data */ + RatList.Size = ratlist_length(&PCB->Data->Rat); + RatList.Data = (void **) calloc(RatList.Size, sizeof(pcb_rat_t *)); + RatList.Location = 0; + RatList.DrawLocation = 0; + RatList.Number = 0; +} + +struct pv_info { + pcb_cardinal_t layer; + pcb_pin_t pv; + jmp_buf env; +}; + +static pcb_r_dir_t LOCtoPVline_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_intersect_line_pin(&i->pv, line) && !PCB_FLAG_TEST(PCB_FLAG_HOLE, &i->pv)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPVarc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, arc) && IS_PV_ON_ARC(&i->pv, arc) && !PCB_FLAG_TEST(PCB_FLAG_HOLE, &i->pv)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPVpad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && IS_PV_ON_PAD(&i->pv, pad) && + !PCB_FLAG_TEST(PCB_FLAG_HOLE, &i->pv) && + ADD_PAD_TO_LIST(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE, pad, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPVrat_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, rat) && IS_PV_ON_RAT(&i->pv, rat) && ADD_RAT_TO_LIST(rat, PCB_TYPE_PIN, &i->pv, PCB_FCT_RAT)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPVpoly_callback(const pcb_box_t * b, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + /* if the pin doesn't have a therm and polygon is clearing + * then it can't touch due to clearance, so skip the expensive + * test. If it does have a therm, you still need to test + * because it might not be inside the polygon, or it could + * be on an edge such that it doesn't actually touch. + */ + if (!PCB_FLAG_TEST(TheFlag, polygon) && !PCB_FLAG_TEST(PCB_FLAG_HOLE, &i->pv) && + (PCB_FLAG_THERM_TEST(i->layer, &i->pv) || !PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon) + || !i->pv.Clearance)) { + double wide = MAX(0.5 * i->pv.Thickness + Bloat, 0); + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, &i->pv)) { + pcb_coord_t x1 = i->pv.X - (i->pv.Thickness + 1 + Bloat) / 2; + pcb_coord_t x2 = i->pv.X + (i->pv.Thickness + 1 + Bloat) / 2; + pcb_coord_t y1 = i->pv.Y - (i->pv.Thickness + 1 + Bloat) / 2; + pcb_coord_t y2 = i->pv.Y + (i->pv.Thickness + 1 + Bloat) / 2; + if (pcb_poly_is_rect_in_p(x1, y1, x2, y2, polygon) + && ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + else if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, &i->pv)) { + pcb_polyarea_t *oct = pcb_poly_from_octagon(i->pv.X, i->pv.Y, i->pv.Thickness / 2, PCB_FLAG_SQUARE_GET(&i->pv)); + if (pcb_poly_isects_poly(oct, polygon, pcb_true) + && ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + else if (pcb_poly_is_point_in_p(i->pv.X, i->pv.Y, wide, polygon) + && ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +struct ps_info { + pcb_layer_id_t layer; + pcb_pstk_t ps; + jmp_buf env; +}; + +static pcb_r_dir_t LOCtoPSline_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct ps_info *i = (struct ps_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_pstk_intersect_line(&i->ps, line)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_PSTK, &i->ps, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPSarc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct ps_info *i = (struct ps_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, arc) && pcb_pstk_intersect_arc(&i->ps, arc)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_PSTK, &i->ps, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPSrat_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + struct ps_info *i = (struct ps_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, rat) && pcb_pstk_intersect_rat(&i->ps, rat) && ADD_RAT_TO_LIST(rat, PCB_TYPE_PIN, &i->ps, PCB_FCT_RAT)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPSpoly_callback(const pcb_box_t * b, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *) b; + struct ps_info *i = (struct ps_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, polygon) && pcb_pstk_intersect_poly(&i->ps, polygon)) { + if (ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_PSTK, &i->ps, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + + return PCB_R_DIR_NOT_FOUND; +} + + +/* --------------------------------------------------------------------------- + * checks if a PV is connected to LOs, if it is, the LO is added to + * the appropriate list and the 'used' flag is set + */ +static pcb_bool LookupLOConnectionsToPVList(pcb_bool AndRats) +{ + pcb_cardinal_t layer; + struct pv_info info; + pcb_pin_t *orig_pin; + + /* loop over all PVs currently on list */ + while (PVList.Location < PVList.Number) { + /* get pointer to data */ + orig_pin = (PVLIST_ENTRY(PVList.Location)); + info.pv = *orig_pin; + EXPAND_BOUNDS(&info.pv); + + /* subc intconn jumps */ + if ((orig_pin->term != NULL) && (orig_pin->intconn > 0)) + LOC_int_conn_subc(pcb_gobj_parent_subc(orig_pin->parent_type, &orig_pin->parent), orig_pin->intconn, PCB_TYPE_PIN, orig_pin); + + /* check pads */ + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, (pcb_box_t *) & info.pv, NULL, LOCtoPVpad_callback, &info, NULL); + else + return pcb_true; + + /* now all lines, arcs and polygons of the several layers */ + for(layer = 0; layer < pcb_max_layer; layer++) { + if (!(pcb_layer_flags(PCB, layer) & PCB_LYT_COPPER)) + continue; + if (LAYER_PTR(layer)->meta.real.no_drc) + continue; + info.layer = layer; + /* add touching lines */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, (pcb_box_t *) & info.pv, NULL, LOCtoPVline_callback, &info, NULL); + else + return pcb_true; + /* add touching arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, (pcb_box_t *) & info.pv, NULL, LOCtoPVarc_callback, &info, NULL); + else + return pcb_true; + /* check all polygons */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->polygon_tree, (pcb_box_t *) & info.pv, NULL, LOCtoPVpoly_callback, &info, NULL); + else + return pcb_true; + } + /* Check for rat-lines that may intersect the PV */ + if (AndRats) { + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, (pcb_box_t *) & info.pv, NULL, LOCtoPVrat_callback, &info, NULL); + else + return pcb_true; + } + PVList.Location++; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if a padstack is connected to LOs, if it is, the LO is added to + * the appropriate list and the 'used' flag is set + */ +static pcb_bool LookupLOConnectionsToPSList(pcb_bool AndRats) +{ + pcb_cardinal_t layer; + struct ps_info info; + pcb_pstk_t *orig_ps; + + /* loop over all PVs currently on list */ + while (PadstackList.Location < PadstackList.Number) { + /* get pointer to data */ + orig_ps = (PADSTACKLIST_ENTRY(PadstackList.Location)); + info.ps = *orig_ps; + EXPAND_BOUNDS(&info.ps); + + /* subc intconn jumps */ + if ((orig_ps->term != NULL) && (orig_ps->intconn > 0)) + LOC_int_conn_subc(pcb_gobj_parent_subc(orig_ps->parent_type, &orig_ps->parent), orig_ps->intconn, PCB_TYPE_PSTK, orig_ps); + + /* now all lines, arcs and polygons of the several layers */ + for(layer = 0; layer < pcb_max_layer; layer++) { + if (!(pcb_layer_flags(PCB, layer) & PCB_LYT_COPPER)) + continue; + if (LAYER_PTR(layer)->meta.real.no_drc) + continue; + info.layer = layer; + /* add touching lines */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, (pcb_box_t *) & info.ps, NULL, LOCtoPSline_callback, &info, NULL); + else + return pcb_true; + /* add touching arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, (pcb_box_t *) & info.ps, NULL, LOCtoPSarc_callback, &info, NULL); + else + return pcb_true; + /* check all polygons */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->polygon_tree, (pcb_box_t *) & info.ps, NULL, LOCtoPSpoly_callback, &info, NULL); + else + return pcb_true; + } + /* Check for rat-lines that may intersect the PV */ + if (AndRats) { + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, (pcb_box_t *) & info.ps, NULL, LOCtoPSrat_callback, &info, NULL); + else + return pcb_true; + } + PadstackList.Location++; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * find all connections between LO at the current list position and new LOs + */ +static pcb_bool LookupLOConnectionsToLOList(pcb_bool AndRats) +{ + pcb_bool done; + pcb_layer_id_t layer; + pcb_layergrp_id_t group; + pcb_cardinal_t i, ratposition, + lineposition[PCB_MAX_LAYER], polyposition[PCB_MAX_LAYER], arcposition[PCB_MAX_LAYER], padposition[2]; + + /* copy the current LO list positions; the original data is changed + * by 'LookupPVPSConnectionsToLOList()' which has to check the same + * list entries plus the new ones + */ + for (i = 0; i < pcb_max_layer; i++) { + lineposition[i] = LineList[i].Location; + polyposition[i] = PolygonList[i].Location; + arcposition[i] = ArcList[i].Location; + } + for (i = 0; i < 2; i++) + padposition[i] = PadList[i].Location; + ratposition = RatList.Location; + + /* loop over all new LOs in the list; recurse until no + * more new connections in the layergroup were found + */ + do { + pcb_cardinal_t *position; + unsigned int flg; + + if (AndRats) { + position = &ratposition; + for (; *position < RatList.Number; (*position)++) { + group = RATLIST_ENTRY(*position)->group1; + if (LookupLOConnectionsToRatEnd(&(RATLIST_ENTRY(*position)->Point1), group)) + return (pcb_true); + group = RATLIST_ENTRY(*position)->group2; + if (LookupLOConnectionsToRatEnd(&(RATLIST_ENTRY(*position)->Point2), group)) + return (pcb_true); + } + } + /* loop over all layergroups */ + for (group = 0; group < PCB->LayerGroups.len; group++) { + pcb_cardinal_t entry; + + for (entry = 0; entry < PCB->LayerGroups.grp[group].len; entry++) { + layer = PCB->LayerGroups.grp[group].lid[entry]; + + /* be aware that the layer number equal pcb_max_layer + * and pcb_max_layer+1 have a special meaning for pads + */ + /* try all new lines */ + position = &lineposition[layer]; + for (; *position < LineList[layer].Number; (*position)++) + if (LookupLOConnectionsToLine(LINELIST_ENTRY(layer, *position), group, pcb_true)) + return (pcb_true); + + /* try all new arcs */ + position = &arcposition[layer]; + for (; *position < ArcList[layer].Number; (*position)++) + if (LookupLOConnectionsToArc(ARCLIST_ENTRY(layer, *position), group)) + return (pcb_true); + + /* try all new polygons */ + position = &polyposition[layer]; + for (; *position < PolygonList[layer].Number; (*position)++) + if (LookupLOConnectionsToPolygon(POLYGONLIST_ENTRY(layer, *position), group)) + return (pcb_true); + } + + /* try all new pads */ + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, group); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) layer = PCB_COMPONENT_SIDE; + else continue; /* skip pads for this group */ + + position = &padposition[layer]; + for (; *position < PadList[layer].Number; (*position)++) + if (LookupLOConnectionsToPad(PADLIST_ENTRY(layer, *position), group)) + return (pcb_true); + } + + /* check if all lists are done; Later for-loops + * may have changed the prior lists + */ + done = !AndRats || ratposition >= RatList.Number; + for (layer = 0; layer < pcb_max_layer; layer++) { + done = done && + lineposition[layer] >= LineList[layer].Number + && arcposition[layer] >= ArcList[layer].Number && polyposition[layer] >= PolygonList[layer].Number; + } + + /* check the two special pad layers */ + for (layer = 0; layer < 2; layer++) + done = done && padposition[layer] >= PadList[layer].Number; + } while (!done); + return (pcb_false); +} + +static pcb_r_dir_t pv_pv_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_t *) b; + struct pv_info *i = (struct pv_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pin) && PV_TOUCH_PV(&i->pv, pin)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) || PCB_FLAG_TEST(PCB_FLAG_HOLE, &i->pv)) { + PCB_FLAG_SET(PCB_FLAG_WARN, pin); + conf_core.temp.rat_warn = pcb_true; + if (pin->Element) + pcb_message(PCB_MSG_WARNING, _("Hole too close to pin.\n")); + else + pcb_message(PCB_MSG_WARNING, _("Hole too close to via.\n")); + } + else if (ADD_PV_TO_LIST(pin, PCB_TYPE_PIN, &i->pv, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches for new PVs that are connected to PVs on the list + */ +static pcb_bool LookupPVConnectionsToPVList(void) +{ + pcb_cardinal_t save_place; + struct pv_info info; + + + /* loop over all PVs on list */ + save_place = PVList.Location; + while (PVList.Location < PVList.Number) { + int ic; + pcb_pin_t *orig_pin; + /* get pointer to data */ + orig_pin = (PVLIST_ENTRY(PVList.Location)); + info.pv = *orig_pin; + + ic = orig_pin->intconn; + if ((info.pv.Element != NULL) && (ic > 0)) + LOC_int_conn_element(info.pv.Element, ic, PCB_TYPE_PIN, orig_pin); + + /* subc intconn jumps */ + if ((orig_pin->term != NULL) && (orig_pin->intconn > 0)) + LOC_int_conn_subc(pcb_gobj_parent_subc(orig_pin->parent_type, &orig_pin->parent), orig_pin->intconn, PCB_TYPE_PIN, orig_pin); + + EXPAND_BOUNDS(&info.pv); + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.pv, NULL, pv_pv_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.pv, NULL, pv_pv_callback, &info, NULL); + else + return pcb_true; + PVList.Location++; + } + PVList.Location = save_place; + return (pcb_false); +} + +struct lo_info { + pcb_layer_id_t layer; + pcb_line_t line; + pcb_pad_t pad; + pcb_arc_t arc; + pcb_poly_t polygon; + pcb_rat_t rat; + jmp_buf env; +}; + +static pcb_r_dir_t pv_line_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pv) && pcb_intersect_line_pin(pv, &i->line)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + PCB_FLAG_SET(PCB_FLAG_WARN, pv); + conf_core.temp.rat_warn = pcb_true; + pcb_message(PCB_MSG_WARNING, _("Hole too close to line.\n")); + } + else if (ADD_PV_TO_LIST(pv, PCB_TYPE_LINE, &i->line, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t ps_line_callback(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, ps) && pcb_pstk_intersect_line(ps, &i->line)) { + if (ADD_PS_TO_LIST(ps, PCB_TYPE_LINE, &i->line, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t pv_pad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pv) && IS_PV_ON_PAD(pv, &i->pad)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + PCB_FLAG_SET(PCB_FLAG_WARN, pv); + conf_core.temp.rat_warn = pcb_true; + pcb_message(PCB_MSG_WARNING, _("Hole too close to pad.\n")); + } + else if (ADD_PV_TO_LIST(pv, PCB_TYPE_PAD, &i->pad, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t pv_arc_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pv) && IS_PV_ON_ARC(pv, &i->arc)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + PCB_FLAG_SET(PCB_FLAG_WARN, pv); + conf_core.temp.rat_warn = pcb_true; + pcb_message(PCB_MSG_WARNING, _("Hole touches arc.\n")); + } + else if (ADD_PV_TO_LIST(pv, PCB_TYPE_ARC, &i->arc, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t ps_arc_callback(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, ps) && pcb_pstk_intersect_arc(ps, &i->arc)) { + if (ADD_PS_TO_LIST(ps, PCB_TYPE_ARC, &i->arc, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t pv_poly_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + /* note that holes in polygons are ok, so they don't generate warnings. */ + if (!PCB_FLAG_TEST(TheFlag, pv) && !PCB_FLAG_TEST(PCB_FLAG_HOLE, pv) && + (PCB_FLAG_THERM_TEST(i->layer, pv) || !PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, &i->polygon) || !pv->Clearance)) { + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pv)) { + pcb_coord_t x1, x2, y1, y2; + x1 = pv->X - (PIN_SIZE(pv) + 1 + Bloat) / 2; + x2 = pv->X + (PIN_SIZE(pv) + 1 + Bloat) / 2; + y1 = pv->Y - (PIN_SIZE(pv) + 1 + Bloat) / 2; + y2 = pv->Y + (PIN_SIZE(pv) + 1 + Bloat) / 2; + if (pcb_poly_is_rect_in_p(x1, y1, x2, y2, &i->polygon) + && ADD_PV_TO_LIST(pv, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + else if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pv)) { + pcb_polyarea_t *oct = pcb_poly_from_octagon(pv->X, pv->Y, PIN_SIZE(pv) / 2, PCB_FLAG_SQUARE_GET(pv)); + if (pcb_poly_isects_poly(oct, &i->polygon, pcb_true) && ADD_PV_TO_LIST(pv, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + else { + if (pcb_poly_is_point_in_p(pv->X, pv->Y, PIN_SIZE(pv) * 0.5 + Bloat, &i->polygon) + && ADD_PV_TO_LIST(pv, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t ps_poly_callback(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, ps) && pcb_pstk_intersect_poly(ps, &i->polygon)) { + if (ADD_PS_TO_LIST(ps, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t pv_rat_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + /* rats can't cause DRC so there is no early exit */ + if (!PCB_FLAG_TEST(TheFlag, pv) && IS_PV_ON_RAT(pv, &i->rat)) + ADD_PV_TO_LIST(pv, PCB_TYPE_RATLINE, &i->rat, PCB_FCT_RAT); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t ps_rat_callback(const pcb_box_t * b, void *cl) +{ + pcb_pstk_t *ps = (pcb_pstk_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + /* rats can't cause DRC so there is no early exit */ + if (!PCB_FLAG_TEST(TheFlag, ps) && pcb_pstk_intersect_rat(ps, &i->rat)) + ADD_PS_TO_LIST(ps, PCB_TYPE_RATLINE, &i->rat, PCB_FCT_RAT); + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches for new PVs and padstacks that are connected to NEW LOs on the list + * This routine updates the position counter of the lists too. + */ +static pcb_bool LookupPVPSConnectionsToLOList(pcb_bool AndRats) +{ + pcb_layer_id_t layer; + struct lo_info info; + + /* loop over all layers */ + for(layer = 0; layer < pcb_max_layer; layer++) { + if (!(pcb_layer_flags(PCB, layer) & PCB_LYT_COPPER)) + continue; + if (LAYER_PTR(layer)->meta.real.no_drc) + continue; + /* do nothing if there are no PV's */ + if (TotalP + TotalV + TotalPs == 0) { + LineList[layer].Location = LineList[layer].Number; + ArcList[layer].Location = ArcList[layer].Number; + PolygonList[layer].Location = PolygonList[layer].Number; + continue; + } + + /* check all lines */ + while (LineList[layer].Location < LineList[layer].Number) { + pcb_line_t *orig_line = (LINELIST_ENTRY(layer, LineList[layer].Location)); + info.line = *orig_line; + EXPAND_BOUNDS(&info.line); + + /* subc intconn jumps */ + if ((orig_line->term != NULL) && (orig_line->intconn > 0)) + LOC_int_conn_subc(pcb_lobj_parent_subc(orig_line->parent_type, &orig_line->parent), orig_line->intconn, PCB_TYPE_LINE, orig_line); + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.line, NULL, pv_line_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.line, NULL, pv_line_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->padstack_tree, (pcb_box_t *) & info.line, NULL, ps_line_callback, &info, NULL); + else + return pcb_true; + LineList[layer].Location++; + } + + /* check all arcs */ + while (ArcList[layer].Location < ArcList[layer].Number) { + pcb_arc_t *orig_arc = (ARCLIST_ENTRY(layer, ArcList[layer].Location)); + info.arc = *orig_arc; + EXPAND_BOUNDS(&info.arc); + + /* subc intconn jumps */ + if ((orig_arc->term != NULL) && (orig_arc->intconn > 0)) + LOC_int_conn_subc(pcb_lobj_parent_subc(orig_arc->parent_type, &orig_arc->parent), orig_arc->intconn, PCB_TYPE_LINE, orig_arc); + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.arc, NULL, pv_arc_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.arc, NULL, pv_arc_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->padstack_tree, (pcb_box_t *) & info.arc, NULL, ps_arc_callback, &info, NULL); + else + return pcb_true; + ArcList[layer].Location++; + } + + /* now all polygons */ + info.layer = layer; + while (PolygonList[layer].Location < PolygonList[layer].Number) { + pcb_poly_t *orig_poly = (POLYGONLIST_ENTRY(layer, PolygonList[layer].Location)); + info.polygon = *orig_poly; + EXPAND_BOUNDS(&info.polygon); + + /* subc intconn jumps */ + if ((orig_poly->term != NULL) && (orig_poly->intconn > 0)) + LOC_int_conn_subc(pcb_lobj_parent_subc(orig_poly->parent_type, &orig_poly->parent), orig_poly->intconn, PCB_TYPE_LINE, orig_poly); + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.polygon, NULL, pv_poly_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.polygon, NULL, pv_poly_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->padstack_tree, (pcb_box_t *) & info.polygon, NULL, ps_poly_callback, &info, NULL); + else + return pcb_true; + PolygonList[layer].Location++; + } + } + + /* loop over all pad-layers */ + for (layer = 0; layer < 2; layer++) { + /* do nothing if there are no PV's */ + if (TotalP + TotalV == 0) { + PadList[layer].Location = PadList[layer].Number; + continue; + } + + /* check all pads; for a detailed description see + * the handling of lines in this subroutine + */ + while (PadList[layer].Location < PadList[layer].Number) { + info.pad = *(PADLIST_ENTRY(layer, PadList[layer].Location)); + EXPAND_BOUNDS(&info.pad); + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, (pcb_box_t *) & info.pad, NULL, pv_pad_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, (pcb_box_t *) & info.pad, NULL, pv_pad_callback, &info, NULL); + else + return pcb_true; + PadList[layer].Location++; + } + } + + /* do nothing if there are no PV's */ + if (TotalP + TotalV == 0) + RatList.Location = RatList.Number; + + /* check all rat-lines */ + if (AndRats) { + while (RatList.Location < RatList.Number) { + info.rat = *(RATLIST_ENTRY(RatList.Location)); + r_search_pt(PCB->Data->via_tree, &info.rat.Point1, 1, NULL, pv_rat_callback, &info, NULL); + r_search_pt(PCB->Data->via_tree, &info.rat.Point2, 1, NULL, pv_rat_callback, &info, NULL); + r_search_pt(PCB->Data->pin_tree, &info.rat.Point1, 1, NULL, pv_rat_callback, &info, NULL); + r_search_pt(PCB->Data->pin_tree, &info.rat.Point2, 1, NULL, pv_rat_callback, &info, NULL); + r_search_pt(PCB->Data->padstack_tree, &info.rat.Point1, 1, NULL, ps_rat_callback, &info, NULL); + r_search_pt(PCB->Data->padstack_tree, &info.rat.Point2, 1, NULL, ps_rat_callback, &info, NULL); + + RatList.Location++; + } + } + return (pcb_false); +} + +pcb_r_dir_t pv_touch_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pin) && pcb_intersect_line_pin(pin, &i->line)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoArcLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_intersect_line_arc(line, &i->arc)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_ARC, &i->arc, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoArcArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!arc->Thickness) + return 0; + if (!PCB_FLAG_TEST(TheFlag, arc) && ArcArcIntersect(&i->arc, arc)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_ARC, &i->arc, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoArcPad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) + && pcb_intersect_arc_pad(&i->arc, pad) && ADD_PAD_TO_LIST(i->layer, pad, PCB_TYPE_ARC, &i->arc, PCB_FCT_COPPER)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoArcRat_callback(const pcb_box_t *b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *)b; + struct lo_info *i = (struct lo_info *)cl; + + if (!PCB_FLAG_TEST(TheFlag, rat)) { + if ((rat->group1 == i->layer) + && IsRatPointOnArcSpec(&rat->Point1, &i->arc)) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_ARC, &i->arc, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + else if ((rat->group2 == i->layer) + && IsRatPointOnArcSpec(&rat->Point2, &i->arc)) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_ARC, &i->arc, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches all LOs that are connected to the given arc on the given + * layergroup. All found connections are added to the list + * + * the notation that is used is: + * Xij means Xj at arc i + */ +static pcb_bool LookupLOConnectionsToArc(pcb_arc_t *Arc, pcb_cardinal_t LayerGroup) +{ + pcb_cardinal_t entry; + struct lo_info info; + unsigned int flg; + + info.arc = *Arc; + EXPAND_BOUNDS(&info.arc); + + + /* loop over all layers of the group */ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + + info.layer = LayerGroup; + + /* add the new rat lines */ + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, &info.arc.BoundingBox, NULL, LOCtoArcRat_callback, &info, NULL); + else + return pcb_true; + + info.layer = layer; + + /* add arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, &info.arc.BoundingBox, NULL, LOCtoArcLine_callback, &info, NULL); + else + return pcb_true; + + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, &info.arc.BoundingBox, NULL, LOCtoArcArc_callback, &info, NULL); + else + return pcb_true; + + /* now check all polygons */ + { + pcb_rtree_it_t it; + pcb_box_t *b; + for(b = pcb_r_first(PCB->Data->Layer[layer].polygon_tree, &it); b != NULL; b = pcb_r_next(&it)) { + pcb_poly_t *polygon = (pcb_poly_t *)b; + if (!PCB_FLAG_TEST(TheFlag, polygon) && pcb_is_arc_in_poly(Arc, polygon) + && ADD_POLYGON_TO_LIST(layer, polygon, PCB_TYPE_ARC, Arc, PCB_FCT_COPPER)) + return pcb_true; + } + pcb_r_end(&it); + } + } + + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, LayerGroup); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) info.layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) info.layer = PCB_COMPONENT_SIDE; + else return pcb_false; + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, &info.arc.BoundingBox, NULL, LOCtoArcPad_callback, &info, NULL); + else + return pcb_true; + + return pcb_false; +} + +static pcb_r_dir_t LOCtoLineLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_intersect_line_line(&i->line, line)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_LINE, &i->line, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoLineArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!arc->Thickness) + return 0; + if (!PCB_FLAG_TEST(TheFlag, arc) && pcb_intersect_line_arc(&i->line, arc)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_LINE, &i->line, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoLineRat_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, rat)) { + if ((rat->group1 == i->layer) + && IsRatPointOnLineSpec(&rat->Point1, &i->line)) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_LINE, &i->line, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + else if ((rat->group2 == i->layer) + && IsRatPointOnLineSpec(&rat->Point2, &i->line)) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_LINE, &i->line, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoLinePad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) + && pcb_intersect_line_pad(&i->line, pad) && ADD_PAD_TO_LIST(i->layer, pad, PCB_TYPE_LINE, &i->line, PCB_FCT_COPPER)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches all LOs that are connected to the given line on the given + * layergroup. All found connections are added to the list + * + * the notation that is used is: + * Xij means Xj at line i + */ +static pcb_bool LookupLOConnectionsToLine(pcb_line_t *Line, pcb_cardinal_t LayerGroup, pcb_bool PolysTo) +{ + pcb_cardinal_t entry; + struct lo_info info; + unsigned int flg; + + info.line = *Line; + info.layer = LayerGroup; + EXPAND_BOUNDS(&info.line) + /* add the new rat lines */ + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, &info.line.BoundingBox, NULL, LOCtoLineRat_callback, &info, NULL); + else + return pcb_true; + + /* loop over all layers of the group */ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + + info.layer = layer; + /* add lines */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, (pcb_box_t *) & info.line, NULL, LOCtoLineLine_callback, &info, NULL); + else + return pcb_true; + /* add arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, (pcb_box_t *) & info.line, NULL, LOCtoLineArc_callback, &info, NULL); + else + return pcb_true; + /* now check all polygons */ + if (PolysTo) { + pcb_rtree_it_t it; + pcb_box_t *b; + for(b = pcb_r_first(PCB->Data->Layer[layer].polygon_tree, &it); b != NULL; b = pcb_r_next(&it)) { + pcb_poly_t *polygon = (pcb_poly_t *)b; + if (!PCB_FLAG_TEST(TheFlag, polygon) && pcb_is_line_in_poly(Line, polygon) + && ADD_POLYGON_TO_LIST(layer, polygon, PCB_TYPE_LINE, Line, PCB_FCT_COPPER)) + return pcb_true; + } + pcb_r_end(&it); + } + } + + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, LayerGroup); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) info.layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) info.layer = PCB_COMPONENT_SIDE; + else return pcb_false; + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, &info.line.BoundingBox, NULL, LOCtoLinePad_callback, &info, NULL); + else + return pcb_true; + + return pcb_false; +} + + +struct rat_info { + pcb_cardinal_t layer; + pcb_point_t *Point; + jmp_buf env; +}; + +static pcb_r_dir_t LOCtoRatLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct rat_info *i = (struct rat_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && IsRatPointOnLineSpec(i->Point, line)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_RATLINE, &i->Point, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoRatArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct rat_info *i = (struct rat_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, arc) && IsRatPointOnArcSpec(i->Point, arc)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_RATLINE, &i->Point, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoRatPoly_callback(const pcb_box_t * b, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *) b; + struct rat_info *i = (struct rat_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, polygon) && polygon->Clipped && IsRatPointOnPoly(i->Point, polygon)) { + if (ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_RATLINE, &i->Point, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct rat_info *i = (struct rat_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == + (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) && + ((pad->Point1.X == i->Point->X && pad->Point1.Y == i->Point->Y) || + (pad->Point2.X == i->Point->X && pad->Point2.Y == i->Point->Y) || + ((pad->Point1.X + pad->Point2.X) / 2 == i->Point->X && + (pad->Point1.Y + pad->Point2.Y) / 2 == i->Point->Y)) && + ADD_PAD_TO_LIST(i->layer, pad, PCB_TYPE_RATLINE, &i->Point, PCB_FCT_RAT)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches all LOs that are connected to the given rat-line on the given + * layergroup. All found connections are added to the list + * + * the notation that is used is: + * Xij means Xj at line i + */ +static pcb_bool LookupLOConnectionsToRatEnd(pcb_point_t *Point, pcb_cardinal_t LayerGroup) +{ + pcb_cardinal_t entry; + struct rat_info info; + unsigned int flg; + + info.Point = Point; + /* loop over all layers of this group */ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + info.layer = layer; + if (setjmp(info.env) == 0) + r_search_pt(LAYER_PTR(layer)->arc_tree, Point, 1, NULL, LOCtoRatArc_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + r_search_pt(LAYER_PTR(layer)->line_tree, Point, 1, NULL, LOCtoRatLine_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + r_search_pt(LAYER_PTR(layer)->polygon_tree, Point, 1, NULL, LOCtoRatPoly_callback, &info, NULL); + } + + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, LayerGroup); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) info.layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) info.layer = PCB_COMPONENT_SIDE; + else return pcb_false; + + if (setjmp(info.env) == 0) + r_search_pt(PCB->Data->pad_tree, Point, 1, NULL, LOCtoPad_callback, &info, NULL); + else + return pcb_true; + + return pcb_false; +} + +static pcb_r_dir_t LOCtoPadLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_intersect_line_pad(line, &i->pad)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_PAD, &i->pad, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPadArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!arc->Thickness) + return 0; + if (!PCB_FLAG_TEST(TheFlag, arc) && pcb_intersect_arc_pad(arc, &i->pad)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_PAD, &i->pad, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPadPoly_callback(const pcb_box_t * b, void *cl) +{ + pcb_poly_t *polygon = (pcb_poly_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + + if (!PCB_FLAG_TEST(TheFlag, polygon) && (!PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, polygon) || !i->pad.Clearance)) { + if (pcb_is_pad_in_poly(&i->pad, polygon) && ADD_POLYGON_TO_LIST(i->layer, polygon, PCB_TYPE_PAD, &i->pad, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPadRat_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + struct lo_info *i = (struct lo_info *) cl; + pcb_layergrp_id_t i_layergrp = i->layer; + + if (!PCB_FLAG_TEST(TheFlag, rat)) { + if (rat->group1 == i_layergrp && + ((rat->Point1.X == i->pad.Point1.X && rat->Point1.Y == i->pad.Point1.Y) || + (rat->Point1.X == i->pad.Point2.X && rat->Point1.Y == i->pad.Point2.Y) || + (rat->Point1.X == (i->pad.Point1.X + i->pad.Point2.X) / 2 && + rat->Point1.Y == (i->pad.Point1.Y + i->pad.Point2.Y) / 2))) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_PAD, &i->pad, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + else if (rat->group2 == i_layergrp && + ((rat->Point2.X == i->pad.Point1.X && rat->Point2.Y == i->pad.Point1.Y) || + (rat->Point2.X == i->pad.Point2.X && rat->Point2.Y == i->pad.Point2.Y) || + (rat->Point2.X == (i->pad.Point1.X + i->pad.Point2.X) / 2 && + rat->Point2.Y == (i->pad.Point1.Y + i->pad.Point2.Y) / 2))) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_PAD, &i->pad, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPadPad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) + && PadPadIntersect(pad, &i->pad) && ADD_PAD_TO_LIST(i->layer, pad, PCB_TYPE_PAD, &i->pad, PCB_FCT_COPPER)) + longjmp(i->env, 1); + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches all LOs that are connected to the given pad on the given + * layergroup. All found connections are added to the list + */ +static pcb_bool LookupLOConnectionsToPad(pcb_pad_t *Pad, pcb_cardinal_t LayerGroup) +{ + pcb_cardinal_t entry; + struct lo_info info; + int ic; + pcb_bool retv = pcb_false; + unsigned int flg; + + /* Internal connection: if pads in the same element have the same + internal connection group number, they are connected */ + ic = Pad->intconn; + if ((Pad->Element != NULL) && (ic > 0)) + LOC_int_conn_element(Pad->Element, ic, PCB_TYPE_PAD, Pad); + + if (!PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad)) + return (LookupLOConnectionsToLine((pcb_line_t *) Pad, LayerGroup, pcb_false)); + + info.pad = *Pad; + EXPAND_BOUNDS(&info.pad); + /* add the new rat lines */ + info.layer = LayerGroup; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, &info.pad.BoundingBox, NULL, LOCtoPadRat_callback, &info, NULL); + else + return pcb_true; + + /* loop over all layers of the group */ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + /* handle normal layers */ + + info.layer = layer; + /* add lines */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, &info.pad.BoundingBox, NULL, LOCtoPadLine_callback, &info, NULL); + else + return pcb_true; + /* add arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, &info.pad.BoundingBox, NULL, LOCtoPadArc_callback, &info, NULL); + else + return pcb_true; + /* add polygons */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->polygon_tree, &info.pad.BoundingBox, NULL, LOCtoPadPoly_callback, &info, NULL); + else + return pcb_true; + } + + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, LayerGroup); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) info.layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) info.layer = PCB_COMPONENT_SIDE; + else return retv; + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, (pcb_box_t *) & info.pad, NULL, LOCtoPadPad_callback, &info, NULL); + else + return pcb_true; + + return retv; +} + +static pcb_r_dir_t LOCtoPolyLine_callback(const pcb_box_t * b, void *cl) +{ + pcb_line_t *line = (pcb_line_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, line) && pcb_is_line_in_poly(line, &i->polygon)) { + if (ADD_LINE_TO_LIST(i->layer, line, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPolyArc_callback(const pcb_box_t * b, void *cl) +{ + pcb_arc_t *arc = (pcb_arc_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!arc->Thickness) + return 0; + if (!PCB_FLAG_TEST(TheFlag, arc) && pcb_is_arc_in_poly(arc, &i->polygon)) { + if (ADD_ARC_TO_LIST(i->layer, arc, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return 0; +} + +static pcb_r_dir_t LOCtoPolyPad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, pad) && i->layer == (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE) + && pcb_is_pad_in_poly(pad, &i->polygon)) { + if (ADD_PAD_TO_LIST(i->layer, pad, PCB_TYPE_POLY, &i->polygon, PCB_FCT_COPPER)) + longjmp(i->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static pcb_r_dir_t LOCtoPolyRat_callback(const pcb_box_t * b, void *cl) +{ + pcb_rat_t *rat = (pcb_rat_t *) b; + struct lo_info *i = (struct lo_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, rat)) { + if (((rat->group1 == i->layer) && IsRatPointOnPoly(&rat->Point1, &i->polygon)) + || ((rat->group2 == i->layer) && IsRatPointOnPoly(&rat->Point2, &i->polygon))) { + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_POLY, &i->polygon, PCB_FCT_RAT)) + longjmp(i->env, 1); + } + } + return PCB_R_DIR_NOT_FOUND; +} + + +/* --------------------------------------------------------------------------- + * looks up LOs that are connected to the given polygon + * on the given layergroup. All found connections are added to the list + */ +static pcb_bool LookupLOConnectionsToPolygon(pcb_poly_t *Polygon, pcb_cardinal_t LayerGroup) +{ + pcb_cardinal_t entry; + struct lo_info info; + unsigned int flg; + + if (!Polygon->Clipped) + return pcb_false; + info.polygon = *Polygon; + EXPAND_BOUNDS(&info.polygon); + info.layer = LayerGroup; + /* check rats */ + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->rat_tree, (pcb_box_t *) & info.polygon, NULL, LOCtoPolyRat_callback, &info, NULL); + else + return pcb_true; +/* loop over all layers of the group */ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + + /* handle normal layers */ + /* check all polygons */ + { + pcb_rtree_it_t it; + pcb_box_t *b; + for(b = pcb_r_first(PCB->Data->Layer[layer].polygon_tree, &it); b != NULL; b = pcb_r_next(&it)) { + pcb_poly_t *polygon = (pcb_poly_t *)b; + if (!PCB_FLAG_TEST(TheFlag, polygon) + && pcb_is_poly_in_poly(polygon, Polygon) + && ADD_POLYGON_TO_LIST(layer, polygon, PCB_TYPE_POLY, Polygon, PCB_FCT_COPPER)) + return pcb_true; + } + pcb_r_end(&it); + } + + info.layer = layer; + /* check all lines */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->line_tree, (pcb_box_t *) & info.polygon, NULL, LOCtoPolyLine_callback, &info, NULL); + else + return pcb_true; + /* check all arcs */ + if (setjmp(info.env) == 0) + pcb_r_search(LAYER_PTR(layer)->arc_tree, (pcb_box_t *) & info.polygon, NULL, LOCtoPolyArc_callback, &info, NULL); + else + return pcb_true; + } + + /* handle the special pad layers */ + flg = pcb_layergrp_flags(PCB, LayerGroup); + if ((flg & PCB_LYT_BOTTOM) && (flg & PCB_LYT_COPPER)) info.layer = PCB_SOLDER_SIDE; + else if ((flg & PCB_LYT_TOP) && (flg & PCB_LYT_COPPER)) info.layer = PCB_COMPONENT_SIDE; + else return pcb_false; + + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pad_tree, (pcb_box_t *) & info.polygon, NULL, LOCtoPolyPad_callback, &info, NULL); + else + return pcb_true; + + return pcb_false; +} Index: tags/1.2.7/src/find_misc.c =================================================================== --- tags/1.2.7/src/find_misc.c (nonexistent) +++ tags/1.2.7/src/find_misc.c (revision 13657) @@ -0,0 +1,608 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "change.h" + +static void DrawNewConnections(void); + +/* --------------------------------------------------------------------------- + * checks if all lists of new objects are handled + */ +static pcb_bool ListsEmpty(pcb_bool AndRats) +{ + pcb_bool empty; + int i; + + empty = (PVList.Location >= PVList.Number) && (PadstackList.Location >= PadstackList.Number); + if (AndRats) + empty = empty && (RatList.Location >= RatList.Number); + for (i = 0; i < pcb_max_layer && empty; i++) + empty = empty && LineList[i].Location >= LineList[i].Number + && ArcList[i].Location >= ArcList[i].Number && PolygonList[i].Location >= PolygonList[i].Number; + return (empty); +} + +static void reassign_no_drc_flags(void) +{ + int layer; +#warning layer TODO: decide whether it is from attribute or not + for (layer = 0; layer < pcb_max_layer; layer++) { + pcb_layer_t *l = LAYER_PTR(layer); + l->meta.real.no_drc = pcb_attribute_get(&l->meta.real.Attributes, "PCB::skip-drc") != NULL; + } +} + + +/* --------------------------------------------------------------------------- + * loops till no more connections are found + */ +static pcb_bool DoIt(pcb_bool AndRats, pcb_bool AndDraw) +{ + pcb_bool newone = pcb_false; + reassign_no_drc_flags(); + do { + /* lookup connections; these are the steps (2) to (4) + * from the description */ + newone = + LookupPVConnectionsToPVList() || + LookupLOConnectionsToPVList(AndRats) || + LookupLOConnectionsToPSList(AndRats) || + LookupLOConnectionsToLOList(AndRats) || + LookupPVPSConnectionsToLOList(AndRats); + if (AndDraw) + DrawNewConnections(); + } + while (!newone && !ListsEmpty(AndRats)); + if (AndDraw) + pcb_draw(); + return (newone); +} + +/* --------------------------------------------------------------------------- + * draws all new connections which have been found since the + * routine was called the last time + */ +static void DrawNewConnections(void) +{ + int i; + pcb_cardinal_t position; + + /* decrement 'i' to keep layerstack order */ + for (i = pcb_max_layer; i != -1; i--) { + pcb_cardinal_t layer = pcb_layer_stack[i]; + + if (PCB->Data->Layer[layer].meta.real.vis) { + /* draw all new lines */ + position = LineList[layer].DrawLocation; + for (; position < LineList[layer].Number; position++) + pcb_line_invalidate_draw(LAYER_PTR(layer), LINELIST_ENTRY(layer, position)); + LineList[layer].DrawLocation = LineList[layer].Number; + + /* draw all new arcs */ + position = ArcList[layer].DrawLocation; + for (; position < ArcList[layer].Number; position++) + pcb_arc_invalidate_draw(LAYER_PTR(layer), ARCLIST_ENTRY(layer, position)); + ArcList[layer].DrawLocation = ArcList[layer].Number; + + /* draw all new polygons */ + position = PolygonList[layer].DrawLocation; + for (; position < PolygonList[layer].Number; position++) + pcb_poly_invalidate_draw(LAYER_PTR(layer), POLYGONLIST_ENTRY(layer, position)); + PolygonList[layer].DrawLocation = PolygonList[layer].Number; + } + } + + /* draw all new pads */ + if (PCB->PinOn) + for (i = 0; i < 2; i++) { + position = PadList[i].DrawLocation; + + for (; position < PadList[i].Number; position++) + pcb_pad_invalidate_draw(PADLIST_ENTRY(i, position)); + PadList[i].DrawLocation = PadList[i].Number; + } + + /* draw all new PVs; 'PVList' holds a list of pointers to the + * sorted array pointers to PV data + */ + while (PVList.DrawLocation < PVList.Number) { + pcb_pin_t *pv = PVLIST_ENTRY(PVList.DrawLocation); + + if (PCB_FLAG_TEST(PCB_FLAG_PIN, pv)) { + if (PCB->PinOn) + pcb_pin_invalidate_draw(pv); + } + else if (PCB->ViaOn) + pcb_via_invalidate_draw(pv); + PVList.DrawLocation++; + } + + /* draw all new Padstacks; 'PadstackList' holds a list of pointers to the + * sorted array pointers to padstack data + */ + while (PadstackList.DrawLocation < PadstackList.Number) { + pcb_pstk_t *ps = PADSTACKLIST_ENTRY(PadstackList.DrawLocation); + + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, ps)) { + if (PCB->PinOn) + pcb_pstk_invalidate_draw(ps); + } + else if (PCB->ViaOn) + pcb_pstk_invalidate_draw(ps); + PadstackList.DrawLocation++; + } + + /* draw the new rat-lines */ + if (PCB->RatOn) { + position = RatList.DrawLocation; + for (; position < RatList.Number; position++) + pcb_rat_invalidate_draw(RATLIST_ENTRY(position)); + RatList.DrawLocation = RatList.Number; + } +} + +/*--------------------------------------------------------------------------- + * add the starting object to the list of found objects + */ +static pcb_bool ListStart(pcb_any_obj_t *obj) +{ + DumpList(); + switch (obj->type) { + case PCB_OBJ_PIN: + case PCB_OBJ_VIA: + { + if (ADD_PV_TO_LIST((pcb_pin_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_PSTK: + { + if (ADD_PADSTACK_TO_LIST((pcb_pstk_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_RAT: + { + if (ADD_RAT_TO_LIST((pcb_rat_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_LINE: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, obj->parent.layer); + if (ADD_LINE_TO_LIST(layer, (pcb_line_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_ARC: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, obj->parent.layer); + if (ADD_ARC_TO_LIST(layer, (pcb_arc_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_POLY: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, obj->parent.layer); + if (ADD_POLYGON_TO_LIST(layer, (pcb_poly_t *)obj, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_OBJ_PAD: + { + pcb_pad_t *pad = (pcb_pad_t *)obj; + if (ADD_PAD_TO_LIST(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE, pad, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + default: + assert(!"unhandled object type: can't start a find list from this\n"); + } + return (pcb_false); +} + + +/* --------------------------------------------------------------------------- + * looks up all connections from the object at the given coordinates + * the TheFlag (normally 'PCB_FLAG_FOUND') is set for all objects found + * the objects are re-drawn if AndDraw is pcb_true + * also the action is marked as undoable if AndDraw is pcb_true + */ +void pcb_lookup_conn(pcb_coord_t X, pcb_coord_t Y, pcb_bool AndDraw, pcb_coord_t Range, int which_flag) +{ + void *ptr1, *ptr2, *ptr3; + char *name; + int type; + + /* check if there are any pins or pads at that position */ + + reassign_no_drc_flags(); + + type = pcb_search_obj_by_location(PCB_LOOKUP_FIRST, &ptr1, &ptr2, &ptr3, X, Y, Range); + if (type == PCB_TYPE_NONE) { + type = pcb_search_obj_by_location(PCB_LOOKUP_MORE, &ptr1, &ptr2, &ptr3, X, Y, Range); + if (type == PCB_TYPE_NONE) + return; + if (type & PCB_SILK_TYPE) { + /* don't mess with non-conducting objects! */ + if (!(pcb_layer_flags_((pcb_layer_t *)ptr1) & PCB_LYT_COPPER) || ((pcb_layer_t *) ptr1)->meta.real.no_drc) + return; + } + } + else { + name = pcb_connection_name(ptr2); + pcb_hid_actionl("NetlistShow", name, NULL); + } + + TheFlag = which_flag; + User = AndDraw; + pcb_conn_lookup_init(); + + /* now add the object to the appropriate list and start scanning + * This is step (1) from the description + */ + ListStart(ptr2); + DoIt(pcb_true, AndDraw); + if (User) + pcb_undo_inc_serial(); + User = pcb_false; + + /* we are done */ + if (AndDraw) + pcb_draw(); + if (AndDraw && conf_core.editor.beep_when_finished) + pcb_gui->beep(); + pcb_conn_lookup_uninit(); +} + +void pcb_lookup_conn_by_pin(int type, void *ptr1) +{ + User = 0; + pcb_conn_lookup_init(); + ListStart(ptr1); + + DoIt(pcb_true, pcb_false); + + pcb_conn_lookup_uninit(); +} + +#warning cleanup TODO: keep only PCB_OBJ_* and remove this function +unsigned long pcb_obj_type2oldtype(pcb_objtype_t type) +{ + switch(type) { + case PCB_OBJ_LINE: return PCB_TYPE_LINE; + case PCB_OBJ_TEXT: return PCB_TYPE_TEXT; + case PCB_OBJ_POLY: return PCB_TYPE_POLY; + case PCB_OBJ_ARC: return PCB_TYPE_ARC; + case PCB_OBJ_RAT: return PCB_TYPE_RATLINE; + case PCB_OBJ_PAD: return PCB_TYPE_PAD; + case PCB_OBJ_PIN: return PCB_TYPE_PIN; + case PCB_OBJ_VIA: return PCB_TYPE_VIA; + case PCB_OBJ_PSTK: return PCB_TYPE_PSTK; + case PCB_OBJ_ELEMENT: return PCB_TYPE_ELEMENT; + case PCB_OBJ_SUBC: return PCB_TYPE_SUBC; + + case PCB_OBJ_ELINE: return PCB_TYPE_ELEMENT_LINE; + case PCB_OBJ_ETEXT: return PCB_TYPE_ELEMENT_NAME; + case PCB_OBJ_EARC: return PCB_TYPE_ELEMENT_ARC; + + default: return 0; + } + return 0; +} + +pcb_cardinal_t pcb_lookup_conn_by_obj(void *ctx, pcb_any_obj_t *obj, pcb_bool AndDraw, pcb_cardinal_t (*cb)(void *ctx, pcb_any_obj_t *obj)) +{ + pcb_cardinal_t i, n, cnt = 0; + unsigned long type = pcb_obj_type2oldtype(obj->type); + + if (type == 0) + return 0; + + pcb_conn_lookup_init(); + ListStart(obj); + DoIt(pcb_true, AndDraw); + + for (i = 0; i < pcb_max_layer; i++) { + for(n = 0; n < LineList[i].Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)LineList[i].Data[n]); + for(n = 0; n < ArcList[i].Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)ArcList[i].Data[n]); + for(n = 0; n < PolygonList[i].Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)PolygonList[i].Data[n]); + } + + for (i = 0; i < 2; i++) + for(n = 0; n < PadList[i].Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)PadList[i].Data[n]); + + for(n = 0; n < PVList.Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)PVList.Data[n]); + for(n = 0; n < PadstackList.Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)PadstackList.Data[n]); + for(n = 0; n < RatList.Number; n++) + cnt += cb(ctx, (pcb_any_obj_t *)RatList.Data[n]); + + pcb_conn_lookup_uninit(); + return cnt; +} + + +/* --------------------------------------------------------------------------- + * find connections for rats nesting + * assumes pcb_conn_lookup_init() has already been done + */ +void pcb_rat_find_hook(pcb_any_obj_t *obj, pcb_bool undo, pcb_bool AndRats) +{ + User = undo; + DumpList(); + ListStart(obj); + DoIt(AndRats, pcb_false); + User = pcb_false; +} + +/* --------------------------------------------------------------------------- + * resets all used flags of pins and vias + */ +static pcb_bool pcb_reset_found_pins_vias_pads_(pcb_data_t *data, pcb_bool AndDraw) +{ + pcb_bool change = pcb_false; + + PCB_VIA_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, via)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_CLEAR(TheFlag, via); + if (AndDraw) + pcb_via_invalidate_draw(via); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_PADSTACK_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, padstack)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(padstack); + PCB_FLAG_CLEAR(TheFlag, padstack); + if (AndDraw) + pcb_pstk_invalidate_draw(padstack); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_ELEMENT_LOOP(data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(TheFlag, pin)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_CLEAR(TheFlag, pin); + if (AndDraw) + pcb_pin_invalidate_draw(pin); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (PCB_FLAG_TEST(TheFlag, pad)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_CLEAR(TheFlag, pad); + if (AndDraw) + pcb_pad_invalidate_draw(pad); + change = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(data); + { + pcb_flag_change(PCB, PCB_CHGFLG_CLEAR, PCB_FLAG_FOUND, PCB_TYPE_SUBC, subc, subc, subc); + if (pcb_reset_found_pins_vias_pads_(subc->data, AndDraw)) + change = pcb_true; + } + PCB_END_LOOP; + + return change; +} + +pcb_bool pcb_reset_found_pins_vias_pads(pcb_bool AndDraw) +{ + pcb_bool change = pcb_reset_found_pins_vias_pads_(PCB->Data, AndDraw); + + if (change) + pcb_board_set_changed_flag(pcb_true); + + return change; +} + +/* --------------------------------------------------------------------------- + * resets all used flags of LOs + */ +static pcb_bool pcb_reset_found_lines_polys_(pcb_data_t *data, pcb_bool AndDraw) +{ + pcb_bool change = pcb_false; + + PCB_RAT_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(TheFlag, line); + if (AndDraw) + pcb_rat_invalidate_draw(line); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_LINE_COPPER_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_CLEAR(TheFlag, line); + if (AndDraw) + pcb_line_invalidate_draw(layer, line); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_ARC_COPPER_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, arc)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_CLEAR(TheFlag, arc); + if (AndDraw) + pcb_arc_invalidate_draw(layer, arc); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_POLY_COPPER_LOOP(data); + { + if (PCB_FLAG_TEST(TheFlag, polygon)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_CLEAR(TheFlag, polygon); + if (AndDraw) + pcb_poly_invalidate_draw(layer, polygon); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + + + PCB_SUBC_LOOP(data); + { + pcb_flag_change(PCB, PCB_CHGFLG_CLEAR, PCB_FLAG_FOUND, PCB_TYPE_SUBC, subc, subc, subc); + if (pcb_reset_found_lines_polys_(subc->data, AndDraw)) + change = pcb_true; + } + PCB_END_LOOP; + + return change; +} + +pcb_bool pcb_reset_found_lines_polys(pcb_bool AndDraw) +{ + pcb_bool change = pcb_reset_found_lines_polys_(PCB->Data, AndDraw); + if (change) + pcb_board_set_changed_flag(pcb_true); + return change; + +} + + +/* --------------------------------------------------------------------------- + * resets all found connections + */ +pcb_bool pcb_reset_conns(pcb_bool AndDraw) +{ + pcb_bool change = pcb_false; + + change = pcb_reset_found_pins_vias_pads(AndDraw) || change; + change = pcb_reset_found_lines_polys(AndDraw) || change; + + return change; +} + +/*---------------------------------------------------------------------------- + * Dumps the list contents + */ +static void DumpList(void) +{ + pcb_cardinal_t i; + + for (i = 0; i < 2; i++) { + PadList[i].Number = 0; + PadList[i].Location = 0; + PadList[i].DrawLocation = 0; + } + + PVList.Number = 0; + PVList.Location = 0; + + PadstackList.Number = 0; + PadstackList.Location = 0; + + for (i = 0; i < pcb_max_layer; i++) { + LineList[i].Location = 0; + LineList[i].DrawLocation = 0; + LineList[i].Number = 0; + ArcList[i].Location = 0; + ArcList[i].DrawLocation = 0; + ArcList[i].Number = 0; + PolygonList[i].Location = 0; + PolygonList[i].DrawLocation = 0; + PolygonList[i].Number = 0; + } + RatList.Number = 0; + RatList.Location = 0; + RatList.DrawLocation = 0; +} + +/*---------------------------------------------------------------------------- + * set up a temporary flag to use + */ +void pcb_save_find_flag(int NewFlag) +{ + OldFlag = TheFlag; + TheFlag = NewFlag; +} + +/*---------------------------------------------------------------------------- + * restore flag + */ +void pcb_restore_find_flag(void) +{ + TheFlag = OldFlag; +} + +void pcb_conn_lookup_init(void) +{ + pcb_component_lookup_init(); + pcb_layout_lookup_init(); +} + +void pcb_conn_lookup_uninit(void) +{ + pcb_component_lookup_uninit(); + pcb_layout_lookup_uninit(); +} Index: tags/1.2.7/src/find_print.c =================================================================== --- tags/1.2.7/src/find_print.c (nonexistent) +++ tags/1.2.7/src/find_print.c (revision 13657) @@ -0,0 +1,293 @@ +/* + * + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Connection export/output functions */ + +static pcb_bool PrepareNextLoop(FILE * FP); + +/* --------------------------------------------------------------------------- + * prints all unused pins of an element to file FP + */ +static pcb_bool PrintAndSelectUnusedPinsAndPadsOfElement(pcb_element_t *Element, FILE * FP) +{ + pcb_bool first = pcb_true; + pcb_cardinal_t number; + + /* check all pins in element */ + +#warning padstack TODO: term TODO: this does not handle padstacks or terminals + + PCB_PIN_LOOP(Element); + { + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { + /* pin might have bee checked before, add to list if not */ + if (!PCB_FLAG_TEST(TheFlag, pin) && FP) { + int i; + if (ADD_PV_TO_LIST(pin, 0, NULL, 0)) + return pcb_true; + DoIt(pcb_true, pcb_true); + number = PadList[PCB_COMPONENT_SIDE].Number + PadList[PCB_SOLDER_SIDE].Number + PVList.Number; + /* the pin has no connection if it's the only + * list entry; don't count vias + */ + for (i = 0; i < PVList.Number; i++) + if (!PVLIST_ENTRY(i)->Element) + number--; + if (number == 1) { + /* output of element name if not already done */ + if (first) { + PrintConnectionElementName(Element, FP); + first = pcb_false; + } + + /* write name to list and draw selected object */ + fputc('\t', FP); + pcb_print_quoted_string(FP, (char *) PCB_EMPTY(pin->Name)); + fputc('\n', FP); + PCB_FLAG_SET(PCB_FLAG_SELECTED, pin); + pcb_pin_invalidate_draw(pin); + } + + /* reset found objects for the next pin */ + if (PrepareNextLoop(FP)) + return (pcb_true); + } + } + } + PCB_END_LOOP; + + /* check all pads in element */ + PCB_PAD_LOOP(Element); + { + /* lookup pad in list */ + /* pad might has bee checked before, add to list if not */ + if (!PCB_FLAG_TEST(TheFlag, pad) && FP) { + int i; + if (ADD_PAD_TO_LIST(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) + ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE, pad, 0, NULL, 0)) + return pcb_true; + DoIt(pcb_true, pcb_true); + number = PadList[PCB_COMPONENT_SIDE].Number + PadList[PCB_SOLDER_SIDE].Number + PVList.Number; + /* the pin has no connection if it's the only + * list entry; don't count vias + */ + for (i = 0; i < PVList.Number; i++) + if (!PVLIST_ENTRY(i)->Element) + number--; + if (number == 1) { + /* output of element name if not already done */ + if (first) { + PrintConnectionElementName(Element, FP); + first = pcb_false; + } + + /* write name to list and draw selected object */ + fputc('\t', FP); + pcb_print_quoted_string(FP, (char *) PCB_EMPTY(pad->Name)); + fputc('\n', FP); + + PCB_FLAG_SET(PCB_FLAG_SELECTED, pad); + pcb_pad_invalidate_draw(pad); + } + + /* reset found objects for the next pin */ + if (PrepareNextLoop(FP)) + return (pcb_true); + } + } + PCB_END_LOOP; + + /* print separator if element has unused pins or pads */ + if (!first) { + fputs("}\n\n", FP); + SEPARATE(FP); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * resets some flags for looking up the next pin/pad + */ +static pcb_bool PrepareNextLoop(FILE * FP) +{ + pcb_cardinal_t layer; + + /* reset found LOs for the next pin */ + for (layer = 0; layer < pcb_max_layer; layer++) { + LineList[layer].Location = LineList[layer].Number = 0; + ArcList[layer].Location = ArcList[layer].Number = 0; + PolygonList[layer].Location = PolygonList[layer].Number = 0; + } + + /* reset found pads */ + for (layer = 0; layer < 2; layer++) + PadList[layer].Location = PadList[layer].Number = 0; + + /* reset PVs */ + PVList.Number = PVList.Location = 0; + RatList.Number = RatList.Location = 0; + + /* reset Padstacks */ + PadstackList.Number = PadstackList.Location = 0; + + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * finds all connections to the pins of the passed element. + * The result is written to file FP + * Returns pcb_true if operation was aborted + */ +static pcb_bool PrintElementConnections(pcb_element_t *Element, FILE * FP, pcb_bool AndDraw) +{ + PrintConnectionElementName(Element, FP); + + /* check all pins in element */ + PCB_PIN_LOOP(Element); + { + /* pin might have been checked before, add to list if not */ + if (PCB_FLAG_TEST(TheFlag, pin)) { + PrintConnectionListEntry((char *) PCB_EMPTY(pin->Name), NULL, pcb_true, FP); + fputs("\t\t__CHECKED_BEFORE__\n\t}\n", FP); + continue; + } + if (ADD_PV_TO_LIST(pin, PCB_TYPE_ELEMENT, Element, PCB_FCT_ELEMENT)) + return pcb_true; + DoIt(pcb_true, AndDraw); + /* printout all found connections */ + PrintPinConnections(FP, pcb_true); + PrintPadConnections(PCB_COMPONENT_SIDE, FP, pcb_false); + PrintPadConnections(PCB_SOLDER_SIDE, FP, pcb_false); + fputs("\t}\n", FP); + if (PrepareNextLoop(FP)) + return (pcb_true); + } + PCB_END_LOOP; + + /* check all pads in element */ + PCB_PAD_LOOP(Element); + { + pcb_cardinal_t layer; + /* pad might have been checked before, add to list if not */ + if (PCB_FLAG_TEST(TheFlag, pad)) { + PrintConnectionListEntry((char *) PCB_EMPTY(pad->Name), NULL, pcb_true, FP); + fputs("\t\t__CHECKED_BEFORE__\n\t}\n", FP); + continue; + } + layer = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE; + if (ADD_PAD_TO_LIST(layer, pad, PCB_TYPE_ELEMENT, Element, PCB_FCT_ELEMENT)) + return pcb_true; + DoIt(pcb_true, AndDraw); + /* print all found connections */ + PrintPadConnections(layer, FP, pcb_true); + PrintPadConnections(layer == (PCB_COMPONENT_SIDE ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE), FP, pcb_false); + PrintPinConnections(FP, pcb_false); + fputs("\t}\n", FP); + if (PrepareNextLoop(FP)) + return (pcb_true); + } + PCB_END_LOOP; + fputs("}\n\n", FP); + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * find all unused pins of all element + */ +void pcb_lookup_unused_pins(FILE * FP) +{ + /* reset all currently marked connections */ + User = pcb_true; + pcb_reset_conns(pcb_true); + pcb_conn_lookup_init(); + + PCB_ELEMENT_LOOP(PCB->Data); + { + /* break if abort dialog returned pcb_true; + * passing NULL as filedescriptor discards the normal output + */ + if (PrintAndSelectUnusedPinsAndPadsOfElement(element, FP)) + break; + } + PCB_END_LOOP; + + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); + pcb_conn_lookup_uninit(); + pcb_undo_inc_serial(); + User = pcb_false; + pcb_draw(); +} + +/* --------------------------------------------------------------------------- + * find all connections to pins within one element + */ +void pcb_lookup_element_conns(pcb_element_t *Element, FILE * FP) +{ + /* reset all currently marked connections */ + User = pcb_true; + TheFlag = PCB_FLAG_FOUND; + pcb_reset_conns(pcb_true); + pcb_conn_lookup_init(); + PrintElementConnections(Element, FP, pcb_true); + pcb_board_set_changed_flag(pcb_true); + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); + pcb_conn_lookup_uninit(); + pcb_undo_inc_serial(); + User = pcb_false; + pcb_draw(); +} + + +/* --------------------------------------------------------------------------- + * find all connections to pins of all element + */ +void pcb_lookup_conns_to_all_elements(FILE * FP) +{ + /* reset all currently marked connections */ + User = pcb_false; + TheFlag = PCB_FLAG_FOUND; + pcb_reset_conns(pcb_false); + pcb_conn_lookup_init(); + + PCB_ELEMENT_LOOP(PCB->Data); + { + /* break if abort dialog returned pcb_true */ + if (PrintElementConnections(element, FP, pcb_false)) + break; + SEPARATE(FP); + if (conf_core.editor.reset_after_element && gdl_it_idx(&__it__) != 1) + pcb_reset_conns(pcb_false); + } + PCB_END_LOOP; + if (conf_core.editor.beep_when_finished) + pcb_gui->beep(); + pcb_reset_conns(pcb_false); + pcb_conn_lookup_uninit(); + pcb_redraw(); +} Index: tags/1.2.7/src/flag.c =================================================================== --- tags/1.2.7/src/flag.c (nonexistent) +++ tags/1.2.7/src/flag.c (revision 13657) @@ -0,0 +1,86 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include +#include +#include "config.h" +#include "flag.h" +#include "operation.h" +#include "obj_all_op.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); +} Index: tags/1.2.7/src/flag.h =================================================================== --- tags/1.2.7/src/flag.h (nonexistent) +++ tags/1.2.7/src/flag.h (revision 13657) @@ -0,0 +1,202 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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; +}; + +typedef struct { + unsigned long f; /* generic flags */ + unsigned char t[(PCB_MAX_LAYER + 1) / 2]; /* thermals */ + unsigned char q; /* square geometry flag */ + pcb_unknown_flag_t *unknowns; +} pcb_flag_t; + +extern pcb_flag_t no_flags; + +/* --------------------------------------------------------------------------- + * object flags + */ + +/* %start-doc pcbfile ~objectflags +@node Object Flags +@section Object Flags + +Note that object flags can be given numerically (like @code{0x0147}) +or symbolically (like @code{"found,showname,square"}. Some numeric +values are reused for different object types. The table below lists +the numeric value followed by the symbolic name. + +Explanation of each bit can be found in flag_str.c + +%end-doc */ +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; + +/* --------------------------------------------------------------------------- + * PCB flags - kept only for file format compatibility reasons; these bits + should be a mirror of booleans from the conf. + */ + +/* ++@item 0x800000 ++snap to certain off-grid points. ++@item 0x1000000 ++highlight lines and arcs when the crosshair is on one of their endpoints. +*/ + +#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) + +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_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)) + +#endif Index: tags/1.2.7/src/flag_str.c =================================================================== --- tags/1.2.7/src/flag_str.c (nonexistent) +++ tags/1.2.7/src/flag_str.c (revision 13657) @@ -0,0 +1,589 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "const.h" +#include "flag_str.h" +#include "compat_misc.h" +#include "macro.h" + +/* Because all the macros expect it, that's why. */ +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_TYPEMASK_ALL, "If set, this object is a pin. This flag is for internal use only." }, + {FN(PCB_FLAG_VIA), N("via"), PCB_TYPEMASK_ALL, "If set, this object is a via. This flag is for internal use only." }, + {FN(PCB_FLAG_FOUND), N("found"), PCB_TYPEMASK_ALL, "If set, this object has been found by FindConnection()" }, + {FN(PCB_FLAG_HOLE), N("hole"), PCB_TYPEMASK_PIN, "For pins and vias, this flag means that the pin or via is a hole without a copper annulus." }, + {FN(PCB_FLAG_RAT), N("rat"), PCB_TYPE_RATLINE, "If set for a line, indicates that this line is a rat line instead of a copper trace." }, + {FN(PCB_FLAG_PININPOLY), N("pininpoly"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD, "For pins and pads, this flag is used internally to indicate that the pin or pad overlaps a polygon on some layer." }, + {FN(PCB_FLAG_CLEARPOLY), N("clearpoly"), PCB_TYPE_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. " }, + {FN(PCB_FLAG_HIDENAME), N("hidename"), PCB_TYPE_ELEMENT, "For elements, when set the name of the element is hidden." }, + {FN(PCB_FLAG_DISPLAYNAME), N("showname"), PCB_TYPE_ELEMENT, "OBSOLETE: For elements, when set the names of pins are shown." }, + {FN(PCB_FLAG_CLEARLINE), N("clearline"), PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_TEXT | PCB_TYPE_PSTK, "For lines and arcs, the line/arc will clear polygons instead of connecting to them." }, + {FN(PCB_FLAG_SELECTED), N("selected"), PCB_TYPEMASK_ALL, "Set when the object is selected."}, + {FN(PCB_FLAG_ONSOLDER), N("onsolder"), PCB_TYPE_ELEMENT | PCB_TYPE_PAD | PCB_TYPE_TEXT, "For elements and pads, indicates that they are on the solder side."}, + {FN(PCB_FLAG_AUTO), N("auto"), PCB_TYPEMASK_ALL, "For lines and vias, indicates that these were created by the autorouter."}, + {FN(PCB_FLAG_SQUARE), N("square"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD, "For pins and pads, indicates a square (vs round) pin/pad."}, + {FN(PCB_FLAG_RUBBEREND), N("rubberend"), PCB_TYPE_LINE | PCB_TYPE_ARC, "For lines, used internally for rubber band moves: indicates one end already rubber banding."}, + {FN(PCB_FLAG_WARN), N("warn"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD, "For pins, vias, and pads, set to indicate a warning."}, + {FN(PCB_FLAG_USETHERMAL), N("usetherm"), PCB_TYPEMASK_PIN | PCB_TYPE_LINE | PCB_TYPE_ARC, "Obsolete, indicates that pins/vias should be drawn with thermal fingers."}, + {FN(PCB_FLAG_OCTAGON), N("octagon"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD, "Draw pins and vias as octagons." }, + {FN(PCB_FLAG_DRC), N("drc"), PCB_TYPEMASK_ALL, "Set for objects that fail DRC: flag like FOUND flag for DRC checking."}, + {FN(PCB_FLAG_LOCK), N("lock"), PCB_TYPEMASK_ALL, "Set for locked objects."}, + {FN(PCB_FLAG_EDGE2), N("edge2"), PCB_TYPEMASK_ALL, "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)" }, + {FN(PCB_FLAG_FULLPOLY), N("fullpoly"), PCB_TYPE_POLY, "For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one)." }, + {FN(PCB_FLAG_NOPASTE), N("nopaste"), PCB_TYPE_PAD, "Pad should not receive solderpaste. This is to support fiducials" }, + {FN(PCB_FLAG_NONETLIST), N("nonetlist"), PCB_TYPEMASK_ALL, "element is not on the netlist and should not interfere with the netlist "}, + {FN(PCB_FLAG_TERMNAME), N("termname"), PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_TEXT | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_PSTK | PCB_TYPE_SUBC, "when set the names of pins are shown."}, + {FN(PCB_FLAG_CLEARPOLYPOLY), N("clearpolypoly"), PCB_TYPE_POLY, "For polygons, apply clearance to nearby polygons" }, + {FN(PCB_FLAG_DYNTEXT), N("dyntext"), PCB_TYPE_TEXT, "For text: dynamic string (substitute %patterns%)"}, + {FN(PCB_FLAG_FLOATER), N("floater"), PCB_TYPEMASK_ALL, "subc part can be moved after subc placing"} +}; +#undef N +#undef FN + +const int pcb_object_flagbits_len = PCB_ENTRIES(pcb_object_flagbits); + + +/* + * 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; +} + +/* + * Ok, now the two entry points to this file. The first, string_to_flags, + * is passed a string (usually from parse_y.y) and returns a "set of flags". + * In theory, this can be anything, but for now it's just an integer. Later + * it might be a structure, for example. + * + * Currently, there is no error handling :-P + */ + +static int error_ignore(const char *msg) +{ /* do nothing */ + 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) +{ + 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; + + 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 *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) +{ + return pcb_strflg_common_s2f(flagstring, error, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits), intconn); +} + + +/* + * Given a set of flags for a given type of object, return a string + * which reflects those flags. The only requirement is that this + * string be parseable by string_to_flags. + * + * Note that this function knows a little about what kinds of flags + * will be automatically set by parsing, so it won't (for example) + * include the "via" flag for PCB_TYPE_VIAs because it knows those get + * forcibly set when vias are parsed. + */ + +char *pcb_strflg_common_f2s(pcb_flag_t flags, int object_type, pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn) +{ + 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_TYPE_VIA: + PCB_FLAG_CLEAR(PCB_FLAG_VIA, &fh); + break; + case PCB_TYPE_RATLINE: + PCB_FLAG_CLEAR(PCB_FLAG_RAT, &fh); + break; + case PCB_TYPE_PIN: + PCB_FLAG_CLEAR(PCB_FLAG_PIN, &fh); + break; + } +#endif + + savef = fh; + + len = 3; /* for "()\0" */ + + for (i = 0; i < n_flagbits; i++) + + if ((flagbits[i].object_types & 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++) + if (flagbits[i].object_types & 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) +{ + return pcb_strflg_common_f2s(flags, object_type, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits), intconn); +} + + +#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_TYPEMASK_ALL, pcb_flagbits, PCB_ENTRIES(pcb_flagbits), NULL); +} + +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); +} Index: tags/1.2.7/src/flag_str.h =================================================================== --- tags/1.2.7/src/flag_str.h (nonexistent) +++ tags/1.2.7/src/flag_str.h (revision 13657) @@ -0,0 +1,78 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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; + + /* If set, this entry won't be output unless the object type is one + of these. */ + int object_types; + + char *help; +} 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. */ + +/* 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); + +/* 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. */ +char *pcb_strflg_f2s(pcb_flag_t flags, int object_type, unsigned char *intconn); + +/* 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); +char *pcb_strflg_common_f2s(pcb_flag_t flags, int object_type, pcb_flag_bits_t * flagbits, int n_flagbits, unsigned char *intconn); + +#endif Index: tags/1.2.7/src/font.c =================================================================== --- tags/1.2.7/src/font.c (nonexistent) +++ tags/1.2.7/src/font.c (revision 13657) @@ -0,0 +1,453 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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_nls.h" +#include "compat_misc.h" +#include "event.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); +} + +/* 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(&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); + 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) + 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) + return &pcb->fontkit.dflt; + + 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)) { + pcb_arc_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/1.2.7/src/font.h =================================================================== --- tags/1.2.7/src/font.h (nonexistent) +++ tags/1.2.7/src/font.h (revision 13657) @@ -0,0 +1,96 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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/1.2.7/src/font_act.c =================================================================== --- tags/1.2.7/src/font_act.c (nonexistent) +++ tags/1.2.7/src/font_act.c (revision 13657) @@ -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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include "config.h" +#include +#include "board.h" +#include "hid.h" +#include "error.h" +#include "font.h" +#include "action_helper.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"; + +int pcb_act_load_font_from(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *fname, *sid; + static char *default_file = NULL; + pcb_font_id_t fid, dst_fid = -1; + pcb_font_t *fnt; + int res; + + fname = (argc > 0) ? argv[0] : NULL; + sid = (argc > 1) ? argv[1] : NULL; + + 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", "pcbfont", HID_FILESELECT_READ); + if (fname == NULL) + PCB_ACT_FAIL(load_font_from); + 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; + } + + res = pcb_parse_font(fnt, fname); + pcb_event(PCB_EVENT_FONT_CHANGED, "i", fnt->id); + if (res != 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); + 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"; + +int pcb_act_save_font_to(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *fname, *sid; + static char *default_file = NULL; + pcb_font_id_t fid; + pcb_font_t *fnt; + int res; + + fname = (argc > 0) ? argv[0] : NULL; + sid = (argc > 1) ? argv[1] : NULL; + + 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", "pcbfont", HID_FILESELECT_MAY_NOT_EXIST); + if (fname == NULL) + PCB_ACT_FAIL(save_font_to); + if (default_file != NULL) { + free(default_file); + default_file = NULL; + } + } + + res = pcb_write_font(fnt, fname, "lihata"); + if (res != 0) { + pcb_message(PCB_MSG_ERROR, "SaveFontTo(): failed to save font to %s\n", fname); + return 1; + } + + return 0; +} + + +pcb_hid_action_t font_action_list[] = { + {"LoadFontFrom", 0, pcb_act_load_font_from, + pcb_acth_load_font_from, pcb_acts_load_font_from}, + {"SaveFontTo", 0, pcb_act_save_font_to, + pcb_acth_save_font_to, pcb_acts_save_font_to} +}; + +PCB_REGISTER_ACTIONS(font_action_list, NULL) Index: tags/1.2.7/src/font_internal.c =================================================================== --- tags/1.2.7/src/font_internal.c (nonexistent) +++ tags/1.2.7/src/font_internal.c (revision 13657) @@ -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/1.2.7/src/fptr_cast.c =================================================================== --- tags/1.2.7/src/fptr_cast.c (nonexistent) +++ tags/1.2.7/src/fptr_cast.c (revision 13657) @@ -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. + * + */ + +#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/1.2.7/src/fptr_cast.h =================================================================== --- tags/1.2.7/src/fptr_cast.h (nonexistent) +++ tags/1.2.7/src/fptr_cast.h (revision 13657) @@ -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. + * + */ + +/* 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/1.2.7/src/funchash.c =================================================================== --- tags/1.2.7/src/funchash.c (nonexistent) +++ tags/1.2.7/src/funchash.c (revision 13657) @@ -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. + * + */ + +#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; +} Index: tags/1.2.7/src/funchash.h =================================================================== --- tags/1.2.7/src/funchash.h (nonexistent) +++ tags/1.2.7/src/funchash.h (revision 13657) @@ -0,0 +1,52 @@ +/* + * 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. + * + */ + +#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); + +/* Init-uninit the hash */ +void pcb_funchash_init(void); +void pcb_funchash_uninit(void); + +#endif Index: tags/1.2.7/src/funchash_core.h =================================================================== --- tags/1.2.7/src/funchash_core.h (nonexistent) +++ tags/1.2.7/src/funchash_core.h (revision 13657) @@ -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/1.2.7/src/funchash_core_list.h =================================================================== --- tags/1.2.7/src/funchash_core_list.h (nonexistent) +++ tags/1.2.7/src/funchash_core_list.h (revision 13657) @@ -0,0 +1,131 @@ +/* + 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 +*/ +action_entry(AddSelected) +action_entry(All) +action_entry(AllConnections) +action_entry(AllRats) +action_entry(AllUnusedPins) +action_entry(Arc) +action_entry(Arrow) +action_entry(Block) +action_entry(Description) +action_entry(Cancel) +action_entry(Center) +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(Drag) +action_entry(DrillReport) +action_entry(Element) +action_entry(ElementByName) +action_entry(ElementConnections) +action_entry(ElementToBuffer) +action_entry(Escape) +action_entry(Find) +action_entry(FlipElement) +action_entry(FoundPins) +action_entry(Grid) +action_entry(InsertPoint) +action_entry(Layer) +action_entry(Layout) +action_entry(LayoutAs) +action_entry(LayoutToBuffer) +action_entry(Line) +action_entry(LineSize) +action_entry(Lock) +action_entry(Mirror) +action_entry(Move) +action_entry(MoveSelected) +action_entry(NameOnPCB) +action_entry(Netlist) +action_entry(NetByName) +action_entry(None) +action_entry(Notify) +action_entry(Object) +action_entry(ObjectByName) +action_entry(PasteBuffer) +action_entry(PadByName) +action_entry(PinByName) +action_entry(PinOrPadName) +action_entry(Pinout) +action_entry(Polygon) +action_entry(PolygonHole) +action_entry(PreviousPoint) +action_entry(RatsNest) +action_entry(Rectangle) +action_entry(Redraw) +action_entry(Release) +action_entry(Revert) +action_entry(Remove) +action_entry(RemoveSelected) +action_entry(Report) +action_entry(Reset) +action_entry(ResetLinesAndPolygons) +action_entry(ResetPinsViasAndPads) +action_entry(Restore) +action_entry(Rotate) +action_entry(Save) +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(SelectedTexts) +action_entry(SelectedVias) +action_entry(SelectedRats) +action_entry(Stroke) +action_entry(Subc) +action_entry(Text) +action_entry(TextByName) +action_entry(TextScale) +action_entry(Thermal) +action_entry(ToLayout) +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(Via) +action_entry(ViaByName) +action_entry(Value) +action_entry(ViaDrillingHole) +action_entry(ViaSize) +action_entry(Zoom) + Index: tags/1.2.7/src/global_typedefs.h =================================================================== --- tags/1.2.7/src/global_typedefs.h (nonexistent) +++ tags/1.2.7/src/global_typedefs.h (revision 13657) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +#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_buffer_s pcb_buffer_t; +typedef struct pcb_net_s pcb_net_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_pad_s pcb_pad_t; +typedef struct pcb_pstk_s pcb_pstk_t; +typedef struct pcb_pin_s pcb_pin_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_element_s pcb_element_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 unsigned int pcb_cardinal_t; +typedef unsigned char pcb_uint8_t; /* Don't use in new code. */ + +#include "pcb_bool.h" + +#include "unit.h" + +#endif Index: tags/1.2.7/src/globalconst.h =================================================================== --- tags/1.2.7/src/globalconst.h (nonexistent) +++ tags/1.2.7/src/globalconst.h (revision 13657) @@ -0,0 +1,108 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* global constants + * most of these values are also required by files outside the source tree + * (manuals...) + */ + +#ifndef __GLOBALCONST_INCLUDED__ +#define __GLOBALCONST_INCLUDED__ + +#include "config.h" + + +/* frame between the groundplane and the copper or mask - noone seems + to remember what these two are for; changing them may have unforeseen + side effects. */ +#define PCB_GROUNDPLANEFRAME PCB_MIL_TO_COORD(15) +#define PCB_MASKFRAME PCB_MIL_TO_COORD(3) + +/* --------------------------------------------------------------------------- + * some limit specifications + */ +#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_PADSIZE PCB_MIL_TO_COORD(1) /* min size of a pad */ +#define PCB_MAX_PADSIZE ((pcb_coord_t)PCB_LARGE_VALUE) /* max size of a pad */ +#define PCB_MIN_DRC_VALUE PCB_MIL_TO_COORD(0.1) +#define PCB_MAX_DRC_VALUE PCB_MIL_TO_COORD(500) +#define PCB_MIN_DRC_SILK PCB_MIL_TO_COORD(1) +#define PCB_MAX_DRC_SILK PCB_MIL_TO_COORD(30) +#define PCB_MIN_DRC_DRILL PCB_MIL_TO_COORD(1) +#define PCB_MAX_DRC_DRILL PCB_MIL_TO_COORD(50) +#define PCB_MIN_DRC_RING 0 +#define PCB_MAX_DRC_RING PCB_MIL_TO_COORD(100) +#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 + +#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_ELEMENTNAMES 3 /* number of supported names of an element */ +#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/1.2.7/src/gui_act.c =================================================================== --- tags/1.2.7/src/gui_act.c (nonexistent) +++ tags/1.2.7/src/gui_act.c (revision 13657) @@ -0,0 +1,1874 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "tool.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 "hid_actions.h" +#include "hid_init.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "event.h" +#include "layer.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 "obj_elem_draw.h" +#include "obj_pinvia_draw.h" +#include "obj_pad_draw.h" + +#define CLONE_TYPES PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_VIA | PCB_TYPE_POLY + +/* --------------------------------------------------------------------------- */ +/* Toggle actions are kept for compatibility; new code should use the conf system instead */ +static const char pcb_acts_Display[] = + "Display(NameOnPCB|Description|Value|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."; + +/* %start-doc actions Display + +@table @code + +@item NameOnPCB +@item Description +@item Value +Specify whether all elements show their name, description, or value. + +@item Redraw +Redraw the whole board. + +@item 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. + +@item 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. + +@item CycleCrosshair +Changes crosshair drawing. pcb_crosshair may accept form of 4-ray, +8-ray and 12-ray cross. + +@item ToggleRubberBandMode +If set, moving an object moves all the lines attached to it too. + +@item ToggleStartDirection +If set, each time you set a point in a line, the Clip toggles between +orth-angle and angle-ortho. + +@item ToggleUniqueNames +If set, you will not be permitted to change the name of an element to +match that of another element. + +@item ToggleSnapPin +If set, pin centers and pad end points are treated as additional grid +points that the cursor can snap to. + +@item ToggleSnapOffGridLine +If set, snap at some sensible point along a line. + +@item ToggleHighlightOnPoint +If set, highlights lines and arcs when the crosshair is on one of their +two (end) points. + +@item ToggleLocalRef +If set, the mark is automatically set to the beginning of any move, so +you can see the relative distance you've moved. + +@item 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. + +@item ToggleThindrawPoly +If set, polygons on the screen are drawn as outlines. + +@item 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. + +@item ToggleLiveRoute +If set, the progress of the autorouter will be visible on the screen. + +@item ToggleAutoDRC +If set, you will not be permitted to make connections which violate +the current DRC and netlist settings. + +@item 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. + +@item ToggleOrthoMove +If set, the crosshair is only allowed to move orthogonally from its +previous position. I.e. you can move an element or line up, down, +left, or right, but not up+left or down+right. + +@item ToggleName +Selects whether the pinouts show the pin names or the pin numbers. + +@item 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. + +@item 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. + +@item 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. + +@item 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. + +@item 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. + +@item Grid +Toggles whether the grid is displayed or not. + +@item Pinout +Causes the pinout of the element indicated by the cursor to be +displayed, usually in a separate window. + +@item PinOrPadName +Toggles whether the names of pins, pads, or (yes) vias will be +displayed. If the cursor is over an element, all of its pins and pads +are affected. + +@end table + +%end-doc */ + +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 int pcb_act_Display(int argc, const char **argv, pcb_coord_t childX, pcb_coord_t childY) +{ + const char *function, *str_dir; + int id; + int err = 0; + + function = PCB_ACTION_ARG(0); + str_dir = PCB_ACTION_ARG(1); + + if (function && (!str_dir || !*str_dir)) { + switch (id = pcb_funchash_get(function, NULL)) { + + /* redraw layout */ + case F_ClearAndRedraw: + case F_Redraw: + pcb_redraw(); + break; + + /* change the displayed name of elements */ + case F_Value: + case F_NameOnPCB: + case F_Description: + PCB_ELEMENT_LOOP(PCB->Data); + { + pcb_elem_name_invalidate_erase(element); + } + PCB_END_LOOP; + switch (id) { + case F_Value: + if (conf_core.editor.description || conf_core.editor.name_on_pcb) { + conf_set_editor(description, 0); + conf_set_editor(name_on_pcb, 0); + } + else + conf_set_editor(name_on_pcb, 0); /* need to write once so the event is triggered */ + break; + case F_NameOnPCB: + if (conf_core.editor.description || !conf_core.editor.name_on_pcb) { + conf_set_editor(description, 0); + conf_set_editor(name_on_pcb, 1); + } + else + conf_set_editor(name_on_pcb, 1); /* need to write once so the event is triggered */ + break; + case F_Description: + if (!conf_core.editor.description || conf_core.editor.name_on_pcb) { + conf_set_editor(description, 1); + conf_set_editor(name_on_pcb, 0); + } + else + conf_set_editor(name_on_pcb, 0); /* need to write once so the event is triggered */ + break; + } + PCB_ELEMENT_LOOP(PCB->Data); + { + pcb_elem_name_invalidate_draw(element); + } + PCB_END_LOOP; + pcb_draw(); + break; + + /* toggle line-adjust flag */ + case F_ToggleAllDirections: + conf_toggle_editor(all_direction_lines); + pcb_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_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: + conf_toggle_editor(unique_names); + 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_reset_conns(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_lookup_conn(pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, pcb_true, 1, PCB_FLAG_FOUND); + } + 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); + } + break; + + /* toggle displaying of the grid */ + case F_Grid: + conf_toggle_editor(draw_grid); + pcb_redraw(); + break; + + /* display the pinout of an element */ + case F_Pinout: + { + pcb_element_t *element; + void *ptrtmp; + pcb_coord_t x, y; + + pcb_gui->get_coords(_("Click on an element"), &x, &y); + if ((pcb_search_screen(x, y, PCB_TYPE_ELEMENT, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) { + element = (pcb_element_t *) ptrtmp; + pcb_gui->show_item(element); + } + break; + } + + /* toggle displaying of pin/pad/via names */ + case F_PinOrPadName: + { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + pcb_gui->get_coords(_("Click on an element"), &x, &y); + + /* old code for elements */ + switch (pcb_search_screen(x, y, + PCB_TYPE_ELEMENT | PCB_TYPE_PIN | PCB_TYPE_PAD | + PCB_TYPE_VIA, (void **) &ptr1, (void **) &ptr2, (void **) &ptr3)) { + case PCB_TYPE_ELEMENT: + PCB_PIN_LOOP((pcb_element_t *) ptr1); + { + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, pin)) + pcb_pin_name_invalidate_erase(pin); + else + pcb_pin_name_invalidate_draw(pin); + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP((pcb_element_t *) ptr1); + { + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, pad)) + pcb_pad_name_invalidate_erase(pad); + else + pcb_pad_name_invalidate_draw(pad); + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, pad); + } + PCB_END_LOOP; + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + break; + + case PCB_TYPE_PIN: + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, (pcb_pin_t *) ptr2)) + pcb_pin_name_invalidate_erase((pcb_pin_t *) ptr2); + else + pcb_pin_name_invalidate_draw((pcb_pin_t *) ptr2); + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, (pcb_pin_t *) ptr2); + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + break; + + case PCB_TYPE_PAD: + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, (pcb_pad_t *) ptr2)) + pcb_pad_name_invalidate_erase((pcb_pad_t *) ptr2); + else + pcb_pad_name_invalidate_draw((pcb_pad_t *) ptr2); + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, (pcb_pad_t *) ptr2); + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + break; + case PCB_TYPE_VIA: + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, (pcb_pin_t *) ptr2)) + pcb_via_name_invalidate_erase((pcb_pin_t *) ptr2); + else + pcb_via_name_invalidate_draw((pcb_pin_t *) ptr2); + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_TERMNAME, (pcb_pin_t *) ptr2); + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + break; + } + + /* toggle terminal ID print for subcircuit parts */ + type = pcb_search_screen(x, y, PCB_TYPE_SUBC | PCB_TYPE_SUBC_PART | PCB_TYPE_VIA | PCB_TYPE_PSTK | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_TEXT, (void **)&ptr1, (void **)&ptr2, (void **)&ptr3); + if (type) { + pcb_any_obj_t *obj = ptr2; + pcb_opctx_t opctx; + + switch(type) { + case PCB_TYPE_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); + pcb_undo_inc_serial(); + return 0; + break; + case PCB_TYPE_VIA: + case PCB_TYPE_LINE: + case PCB_TYPE_ARC: + case PCB_TYPE_POLY: + case PCB_TYPE_TEXT: + case PCB_TYPE_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 (function && str_dir) { + switch (pcb_funchash_get(function, NULL)) { + case F_ToggleGrid: + if (argc > 2) { + PCB->GridOffsetX = pcb_get_value(argv[1], NULL, NULL, NULL); + PCB->GridOffsetY = pcb_get_value(argv[2], 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."; + +/* %start-doc actions Mode + +@table @code + +@item Arc +@itemx Arrow +@itemx Copy +@itemx InsertPoint +@itemx Line +@itemx Lock +@itemx Move +@itemx None +@itemx PasteBuffer +@itemx Polygon +@itemx Rectangle +@itemx Remove +@itemx Rotate +@itemx Text +@itemx Thermal +@itemx Via +Select the indicated tool. + +@item Notify +Called when you press the mouse button, or move the mouse. + +@item Release +Called when you release the mouse button. + +@item 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. + +@item Escape +Similar to Cancel but calling this action a second time will return +to the Arrow tool. + +@item Stroke +If your @code{pcb} 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. + +@item Save +Remembers the current tool. + +@item Restore +Restores the tool to the last saved tool. + +@end table + +%end-doc */ + +static int pcb_act_Mode(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + + if (function) { + /* 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 (pcb_funchash_get(function, NULL)) { + case F_Arc: + pcb_crosshair_set_mode(PCB_MODE_ARC); + break; + case F_Arrow: + pcb_crosshair_set_mode(PCB_MODE_ARROW); + break; + case F_Copy: + pcb_crosshair_set_mode(PCB_MODE_COPY); + break; + case F_InsertPoint: + pcb_crosshair_set_mode(PCB_MODE_INSERT_POINT); + break; + case F_Line: + pcb_crosshair_set_mode(PCB_MODE_LINE); + break; + case F_Lock: + pcb_crosshair_set_mode(PCB_MODE_LOCK); + break; + case F_Move: + pcb_crosshair_set_mode(PCB_MODE_MOVE); + break; + case F_None: + pcb_crosshair_set_mode(PCB_MODE_NO); + break; + case F_Cancel: + { + int saved_mode = conf_core.editor.mode; + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(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_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(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_crosshair_set_mode(PCB_MODE_ARROW); + else { + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(PCB_MODE_LINE); + } + break; + + case PCB_MODE_RECTANGLE: + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_ARROW); + else { + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(PCB_MODE_RECTANGLE); + } + break; + + case PCB_MODE_POLYGON: + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_ARROW); + else { + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(PCB_MODE_POLYGON); + } + break; + + case PCB_MODE_POLYGON_HOLE: + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_ARROW); + else { + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(PCB_MODE_POLYGON_HOLE); + } + break; + + case PCB_MODE_ARC: + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_ARROW); + else { + pcb_crosshair_set_mode(PCB_MODE_NO); + pcb_crosshair_set_mode(PCB_MODE_ARC); + } + break; + + case PCB_MODE_ARROW: + break; + + default: + break; + } + } + break; + + case F_Notify: + pcb_notify_mode(); + break; + case F_PasteBuffer: + pcb_crosshair_set_mode(PCB_MODE_PASTE_BUFFER); + break; + case F_Polygon: + pcb_crosshair_set_mode(PCB_MODE_POLYGON); + break; + case F_PolygonHole: + pcb_crosshair_set_mode(PCB_MODE_POLYGON_HOLE); + break; + case F_Release: + if ((pcb_mid_stroke) && (conf_core.editor.enable_stroke)) + pcb_stub_stroke_finish(); + else + pcb_release_mode(); + break; + case F_Remove: + pcb_crosshair_set_mode(PCB_MODE_REMOVE); + break; + case F_Rectangle: + pcb_crosshair_set_mode(PCB_MODE_RECTANGLE); + break; + case F_Rotate: + pcb_crosshair_set_mode(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_crosshair_set_mode(PCB_MODE_LINE); + } + else if (conf_core.editor.mode == PCB_MODE_ARC && pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_ARC); + else if (conf_core.editor.mode == PCB_MODE_RECTANGLE && pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_RECTANGLE); + else if (conf_core.editor.mode == PCB_MODE_POLYGON && pcb_crosshair.AttachedLine.State != PCB_CH_STATE_FIRST) + pcb_crosshair_set_mode(PCB_MODE_POLYGON); + else { + pcb_crosshair_save_mode(); + pcb_tool_is_saved = pcb_true; + pcb_crosshair_set_mode(PCB_MODE_ARROW); + pcb_notify_mode(); + } + break; + case F_Text: + pcb_crosshair_set_mode(PCB_MODE_TEXT); + break; + case F_Thermal: + pcb_crosshair_set_mode(PCB_MODE_THERMAL); + break; + case F_Via: + pcb_crosshair_set_mode(PCB_MODE_VIA); + break; + + case F_Restore: /* restore the last saved mode */ + pcb_crosshair_restore_mode(); + break; + + case F_Save: /* save currently selected mode */ + pcb_crosshair_save_mode(); + break; + } + pcb_notify_crosshair_change(pcb_true); + return 0; + } + + PCB_ACT_FAIL(Mode); +} + +/* ---------------------------------------------------------------- */ +static const char pcb_acts_CycleDrag[] = "CycleDrag()\n"; + +static const char pcb_acth_CycleDrag[] = "Cycle through which object is being dragged"; + +#define close_enough(a, b) ((((a)-(b)) > 0) ? ((a)-(b) < (PCB_SLOP * pcb_pixel_slop)) : ((a)-(b) > -(PCB_SLOP * pcb_pixel_slop))) +static int pcb_act_CycleDrag(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + void *ptr1, *ptr2, *ptr3; + int over = 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_TYPE_LINE) != PCB_TYPE_NONE) { + /* 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_TYPE_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_TYPE_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_TYPE_ARC_POINT) != PCB_TYPE_NONE) { + 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_TYPE_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_TYPE_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_TYPE_VIA) != PCB_TYPE_NONE) { + pcb_crosshair.AttachedObject.Type = PCB_TYPE_VIA; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = ptr3; + goto switched; + } + else if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, pcb_crosshair.drags[pcb_crosshair.drags_current], PCB_TYPE_PAD) != PCB_TYPE_NONE) { + pcb_crosshair.AttachedObject.Type = PCB_TYPE_ELEMENT; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr1; + pcb_crosshair.AttachedObject.Ptr3 = ptr1; + goto switched; + } + else if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, pcb_crosshair.drags[pcb_crosshair.drags_current], PCB_TYPE_ARC) != PCB_TYPE_NONE) { + pcb_crosshair.AttachedObject.Type = PCB_TYPE_ARC; + pcb_crosshair.AttachedObject.Ptr1 = ptr1; + pcb_crosshair.AttachedObject.Ptr2 = ptr2; + pcb_crosshair.AttachedObject.Ptr3 = ptr3; + goto switched; + } + + } while (over <= 1); + + return -1; + 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."; + +/* %start-doc actions Message + +This action displays a message to the log window. This action is primarily +provided for use by other programs which may interface with PCB. If +multiple arguments are given, each one is sent to the log window +followed by a newline. + +%end-doc */ + +static int pcb_act_Message(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int i; + + if (argc < 1) + PCB_ACT_FAIL(Message); + + for (i = 0; i < argc; i++) { + pcb_message(PCB_MSG_INFO, argv[i]); + pcb_message(PCB_MSG_INFO, "\n"); + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_ToggleHideName[] = "ToggleHideName(Object|SelectedElements)"; + +static const char pcb_acth_ToggleHideName[] = "Toggles the visibility of element names."; + +/* %start-doc actions ToggleHideName + +If names are hidden you won't see them on the screen and they will not +appear on the silk layer when you print the layout. + +%end-doc */ + +static int pcb_act_ToggleHideName(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function && pcb_silk_on(PCB)) { + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_TYPE_ELEMENT, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + pcb_undo_add_obj_to_flag(ptr2); + pcb_elem_name_invalidate_erase((pcb_element_t *) ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_HIDENAME, (pcb_element_t *) ptr2); + pcb_elem_name_invalidate_draw((pcb_element_t *) ptr2); + pcb_draw(); + pcb_undo_inc_serial(); + } + break; + } + case F_SelectedElements: + case F_Selected: + { + pcb_bool changed = pcb_false; + PCB_ELEMENT_LOOP(PCB->Data); + { + if ((PCB_FLAG_TEST(PCB_FLAG_SELECTED, element) || PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_REFDES(element))) + && (PCB_FRONT(element) || PCB->InvisibleObjectsOn)) { + pcb_undo_add_obj_to_flag(element); + pcb_elem_name_invalidate_erase(element); + PCB_FLAG_TOGGLE(PCB_FLAG_HIDENAME, element); + pcb_elem_name_invalidate_draw(element); + changed = pcb_true; + } + } + PCB_END_LOOP; + if (changed) { + pcb_draw(); + pcb_undo_inc_serial(); + } + } + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_MarkCrosshair[] = "MarkCrosshair()\n" "MarkCrosshair(Center)"; + +static const char pcb_acth_MarkCrosshair[] = "Set/Reset the pcb_crosshair mark."; + +/* %start-doc actions MarkCrosshair + +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 @code{Center} argument is given, the mark is moved to the current +cursor location. + +%end-doc */ + +static int pcb_act_MarkCrosshair(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (!function || !*function) { + 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_gui->get_coords(_("Click on new mark"), &pcb_marked.X, &pcb_marked.Y); + pcb_notify_mark_change(pcb_true); + } + } + else if (pcb_funchash_get(function, NULL) == 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_gui->get_coords(_("Click on new mark"), &pcb_marked.X, &pcb_marked.Y); + pcb_notify_mark_change(pcb_true); + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_RouteStyle[] = "RouteStyle(1|2|3|4)"; + +static const char pcb_acth_RouteStyle[] = "Copies the indicated routing style into the current sizes."; + +/* %start-doc actions RouteStyle + +%end-doc */ + +static int pcb_act_RouteStyle(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *str = PCB_ACTION_ARG(0); + pcb_route_style_t *rts; + int number; + + if (str) { + char *end; + 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); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + } + else + pcb_message(PCB_MSG_ERROR, "Error: invalid route style name or index\n"); + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_CreateMenu[] = "CreateMenu(path | path, action, mnemonic, accel, 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)"; + +/* %start-doc actions RouteStyle + +%end-doc */ + +static int pcb_act_CreateMenu(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_ERROR, "Error: can't create menu, there's no GUI hid loaded\n"); + return 1; + } + + if (argc > 0) { + pcb_gui->create_menu(argv[0], (argc > 1) ? argv[1] : NULL, (argc > 2) ? argv[2] : NULL, (argc > 3) ? argv[3] : NULL, (argc > 4) ? argv[4] : NULL, (argc > 5) ? argv[5] : NULL); + 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. "; + +/* %start-doc actions RouteStyle + +%end-doc */ + +static int pcb_act_RemoveMenu(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (pcb_gui == NULL) { + pcb_message(PCB_MSG_ERROR, "can't remove menu, there's no GUI hid loaded\n"); + return 1; + } + + if (pcb_gui->remove_menu == NULL) { + pcb_message(PCB_MSG_ERROR, "can't remove menu, the GUI doesn't support it\n"); + return 1; + } + + if (argc > 0) { + if (pcb_gui->remove_menu(argv[0]) != 0) + pcb_message(PCB_MSG_ERROR, "failed to remove some of the menu items\n"); + return 0; + } + + PCB_ACT_FAIL(RemoveMenu); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SetSame[] = "SetSame()"; + +static const char pcb_acth_SetSame[] = "Sets current layer and sizes to match indicated item."; + +/* %start-doc actions SetSame + +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, drill, etc) according to that item. + +%end-doc */ +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 int pcb_act_SetSame(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + void *ptr1, *ptr2, *ptr3; + int type; + pcb_layer_t *layer = CURRENT; + + type = pcb_search_screen(x, y, CLONE_TYPES, &ptr1, &ptr2, &ptr3); +/* set layer current and size from line or arc */ + switch (type) { + case PCB_TYPE_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_crosshair_set_mode(PCB_MODE_LINE); + pcb_notify_crosshair_change(pcb_true); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case PCB_TYPE_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_crosshair_set_mode(PCB_MODE_ARC); + pcb_notify_crosshair_change(pcb_true); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + case PCB_TYPE_POLY: + layer = (pcb_layer_t *) ptr1; + break; + + case PCB_TYPE_VIA: + pcb_notify_crosshair_change(pcb_false); + set_same_(0, ((pcb_pin_t *) ptr2)->Thickness, ((pcb_pin_t *) ptr2)->DrillingHole, ((pcb_pin_t *) ptr2)->Clearance / 2, NULL); + if (conf_core.editor.mode != PCB_MODE_VIA) + pcb_crosshair_set_mode(PCB_MODE_VIA); + pcb_notify_crosshair_change(pcb_true); + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + break; + + default: + return 1; + } + if (layer != CURRENT) { + pcb_layervis_change_group_vis(pcb_layer_id(PCB->Data, layer), pcb_true, pcb_true); + pcb_redraw(); + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_SwitchHID[] = "SwitchHID(lesstif|gtk|batch)"; + +static const char pcb_acth_SwitchHID[] = "Switch to another HID."; + +/* %start-doc actions SwitchHID + +Switch to another HID. + +%end-doc */ + +static int pcb_act_SwitchHID(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_hid_t *ng = pcb_hid_find_gui(argv[0]); + int chg; + + if (ng == NULL) { + pcb_message(PCB_MSG_ERROR, "No such HID."); + return 1; + } + + pcb_next_gui = ng; + chg = PCB->Changed; + pcb_quit_app(); + PCB->Changed = chg; + + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +/* This action is provided for CLI convenience */ +static const char pcb_acts_FullScreen[] = "pcb_act_FullScreen(on|off|toggle)\n"; + +static const char pcb_acth_FullScreen[] = "Hide widgets to get edit area full screen"; + +static int pcb_act_FullScreen(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *op = argv == NULL ? NULL : argv[0]; + + if ((op == NULL) || (strcmp(op, "toggle") == 0)) + conf_setf(CFR_DESIGN, "editor/fullscreen", -1, "%d", !conf_core.editor.fullscreen, POL_OVERWRITE); + else if (strcmp(op, "on") == 0) + conf_set(CFR_DESIGN, "editor/fullscreen", -1, "1", POL_OVERWRITE); + else if (strcmp(op, "off") == 0) + conf_set(CFR_DESIGN, "editor/fullscreen", -1, "0", POL_OVERWRITE); + + + return 0; +} + +static const char pcb_acts_PCBChanged[] = "PCBChanged([revert])"; +static const char pcb_acth_PCBChanged[] = + "Tells 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 being" + "reloaded, and that it might keep some viewport settings"; +static int pcb_act_PCBChanged(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *rv = argv == NULL ? NULL : argv[0]; + pcb_board_changed((rv != NULL) && (pcb_strcasecmp(rv, "revert") == 0)); + return 0; +} + +static const char pcb_acts_NetlistChanged[] = "NetlistChanged()"; +static const char pcb_acth_NetlistChanged[] = "Tells the GUI that the netlist has changed."; +static int pcb_act_NetlistChanged(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_netlist_changed(0); + return 0; +} + + +static const char pcb_acts_RouteStylesChanged[] = "RouteStylesChanged()"; +static const char pcb_acth_RouteStylesChanged[] = "Tells the GUI that the routing styles have changed."; +static int pcb_act_RouteStylesChanged(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_event(PCB_EVENT_ROUTE_STYLES_CHANGED, NULL); + return 0; +} + +static const char pcb_acts_LibraryChanged[] = "LibraryChanged()"; +static const char pcb_acth_LibraryChanged[] = "Tells the GUI that the libraries have changed."; +static int pcb_act_LibraryChanged(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_event(PCB_EVENT_LIBRARY_CHANGED, NULL); + return 0; +} + +static const char pcb_acts_cursor[] = "Cursor(Type,DeltaUp,DeltaRight,Units)"; +static const char pcb_acth_cursor[] = "Move the cursor."; +/* %start-doc actions Cursor + +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 @var{DeltaUp} may move the +cursor towards the board origin if the board is inverted. + +Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the +viewport to move such that the crosshair is under the mouse cursor. +@samp{Warp} causes the mouse cursor to move to be above the crosshair. + +@var{Units} can be one of the following: + +@table @samp + +@item mil +@itemx mm +The cursor is moved by that amount, in board units. + +@item grid +The cursor is moved by that many grid points. + +@item view +The values are percentages of the viewport's view. Thus, a pan of +@samp{100} would scroll the viewport by exactly the width of the +current view. + +@item board +The values are percentages of the board size. Thus, a move of +@samp{50,50} moves you halfway across the board. + +@end table + +%end-doc */ + +static int pcb_act_Cursor(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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 pan_warp = HID_SC_DO_NOTHING; + double dx, dy; + pcb_coord_t view_width, view_height; + + 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; + + if (argc != 4) + PCB_ACT_FAIL(cursor); + + if (pcb_strcasecmp(argv[0], "pan") == 0) + pan_warp = HID_SC_PAN_VIEWPORT; + else if (pcb_strcasecmp(argv[0], "warp") == 0) + pan_warp = HID_SC_WARP_POINTER; + else + PCB_ACT_FAIL(cursor); + + dx = pcb_get_value_ex(argv[1], argv[3], NULL, extra_units_x, "", NULL); + if (conf_core.editor.view.flip_x) + dx = -dx; + dy = pcb_get_value_ex(argv[2], argv[3], NULL, extra_units_y, "", NULL); + if (!conf_core.editor.view.flip_y) + dy = -dy; + + /* Allow leaving snapped pin/pad/padstack */ + if (pcb_crosshair.snapped_pad) { + pcb_pad_t *pad = pcb_crosshair.snapped_pad; + pcb_coord_t width = pad->Thickness; + pcb_coord_t height = pcb_distance(pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y)+width; + if (pad->Point1.Y == pad->Point2.Y) { + pcb_coord_t tmp = width; + width = height; + height = tmp; + } + if (dx < 0) { + dx -= width/2; + } else if (dx > 0) { + dx += width/2; + } + if (dy < 0) { + dy -= height/2; + } else if (dy > 0) { + dy += height/2; + } + } else if (pcb_crosshair.snapped_pin) { + pcb_pin_t *pin = pcb_crosshair.snapped_pin; + pcb_coord_t radius = pin->Thickness/2; + if (dx < 0) { + dx -= radius; + } else if (dx > 0) { + dx += radius; + } + if (dy < 0) { + dy -= radius; + } else if (dy > 0) { + dy += radius; + } + } else 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); + + 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 int pcb_act_EditLayer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int ret = 0, n, interactive = 1, explicit = 0; + pcb_layer_t *ly = CURRENT; + + for(n = 0; n < argc; n++) { + if (!explicit && (*argv[n] == '@')) { + pcb_layer_id_t lid = pcb_layer_by_name(PCB->Data, argv[n]+1); + if (lid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer named %s\n", argv[n]+1); + return 1; + } + ly = pcb_get_layer(PCB->Data, lid); + explicit = 1; + } + else if (strncmp(argv[n], "name=", 5) == 0) { + interactive = 0; + ret |= pcb_layer_rename_(ly, pcb_strdup(argv[n]+5)); + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(argv[n], "auto=", 5) == 0) { + interactive = 0; + if (istrue(argv[n]+5)) + ly->comb |= PCB_LYC_AUTO; + else + ly->comb &= ~PCB_LYC_AUTO; + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(argv[n], "sub=", 4) == 0) { + interactive = 0; + if (istrue(argv[n]+4)) + ly->comb |= PCB_LYC_SUB; + else + ly->comb &= ~PCB_LYC_SUB; + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(argv[n], "attrib", 6) == 0) { + char *key, *val; + interactive = 0; + n++; + if (n >= argc) { + pcb_message(PCB_MSG_ERROR, "Need an attribute name=value\n", argv[n]+1); + return 1; + } + key = pcb_strdup(argv[n]); + val = strchr(key, '='); + if (val != NULL) { + *val = '\0'; + val++; + if (*val == '\0') + val = NULL; + } + if (val == NULL) + ret |= pcb_attribute_remove(&ly->meta.real.Attributes, key); + else + ret |= pcb_attribute_put(&ly->meta.real.Attributes, key, val); + free(key); + pcb_board_set_changed_flag(pcb_true); + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid EditLayer() command: %s\n", argv[n]); + PCB_ACT_FAIL(EditLayer); + } + } + + if (interactive) { + int ar; + pcb_hid_attr_val_t rv[16]; + pcb_hid_attribute_t attr[] = { + {"name", "logical layer name", PCB_HATT_STRING, 0, 0, {0}, NULL, NULL, 0, NULL, NULL}, + {"sub: drawn using subtraction", NULL, PCB_HATT_BOOL, 0, 0, {0}, NULL, NULL, 0, NULL, NULL}, + {"auto: auto-generated layer", NULL, PCB_HATT_BOOL, 0, 0, {0}, NULL, NULL, 0, NULL, NULL} + }; + + attr[0].default_val.str_value = pcb_strdup(ly->name); + attr[1].default_val.int_value = ly->comb & PCB_LYC_SUB; + attr[2].default_val.int_value = ly->comb & PCB_LYC_AUTO; + + ar = pcb_gui->attribute_dialog(attr,sizeof(attr)/sizeof(attr[0]), rv, "edit layer properies", "Edit the properties of a logical layer", NULL); + + if (ar == 0) { + pcb_layer_combining_t comb = 0; + if (strcmp(ly->name, attr[0].default_val.str_value) != 0) { + ret |= pcb_layer_rename_(ly, (char *)attr[0].default_val.str_value); + attr[0].default_val.str_value = NULL; + pcb_board_set_changed_flag(pcb_true); + } + if (attr[1].default_val.int_value) comb |= PCB_LYC_SUB; + if (attr[2].default_val.int_value) comb |= PCB_LYC_AUTO; + if (ly->comb != comb) { + ly->comb = comb; + pcb_board_set_changed_flag(pcb_true); + } + } + free((char *)attr[0].default_val.str_value); + ret |= ar; + } + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + 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 int pcb_act_EditGroup(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int ret = 0, n, interactive = 1, explicit = 0; + pcb_layergrp_t *g = NULL; + +#warning layer TODO: rewrite this with DAD in two versions (bound and unbound) + if (CURRENT->is_bound) { + pcb_message(PCB_MSG_ERROR, "Can't edit bound layers yet\n"); + return 1; + } + + if (CURRENT != NULL) + g = pcb_get_layergrp(PCB, CURRENT->meta.real.grp); + + for(n = 0; n < argc; n++) { + if (!explicit && (*argv[n] == '@')) { + pcb_layergrp_id_t gid; + if (argv[n][1] == '\0') + gid = pcb_actd_EditGroup_gid; + else + gid = pcb_layergrp_by_name(PCB, argv[n]+1); + if (gid < 0) { + pcb_message(PCB_MSG_ERROR, "Can't find layer group named %s\n", argv[n]+1); + return 1; + } + g = pcb_get_layergrp(PCB, gid); + explicit = 1; + } + else if (strncmp(argv[n], "name=", 5) == 0) { + interactive = 0; + ret |= pcb_layergrp_rename_(g, pcb_strdup(argv[n]+5)); + pcb_board_set_changed_flag(pcb_true); + } + else if (strncmp(argv[n], "type=", 5) == 0) { + const char *sbit = argv[n]+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); + return 1; + } + switch(*sbit) { + case '+': g->type |= bit; break; + case '-': g->type &= ~bit; break; + } + interactive = 0; + pcb_board_set_changed_flag(pcb_true); + } +#if 0 + else if (strncmp(argv[n], "attrib", 6) == 0) { + char *key, *val; + interactive = 0; + n++; + if (n >= argc) { + pcb_message(PCB_MSG_ERROR, "Need an attribute name=value\n", argv[n]+1); + return 1; + } + key = pcb_strdup(argv[n]); + 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); + } +#endif + else { + pcb_message(PCB_MSG_ERROR, "Invalid EditGroup() command: %s\n", argv[n]); + PCB_ACT_FAIL(EditLayer); + } + } + + if (interactive) { + int ar; + pcb_hid_attr_val_t rv[16]; + pcb_hid_attribute_t attr[] = { + {"name", "logical layer name", PCB_HATT_STRING, 0, 0, {0}, NULL, NULL, 0, NULL, NULL}, + }; + + attr[0].default_val.str_value = pcb_strdup(g->name); + + ar = pcb_gui->attribute_dialog(attr,sizeof(attr)/sizeof(attr[0]), rv, "edit layer properies", "Edit the properties of a logical layer", NULL); + + if (ar == 0) { + if (strcmp(g->name, attr[0].default_val.str_value) != 0) { + ret |= pcb_layergrp_rename_(g, (char *)attr[0].default_val.str_value); + attr[0].default_val.str_value = NULL; + pcb_board_set_changed_flag(pcb_true); + } + } + + free((char *)attr[0].default_val.str_value); + + ret |= ar; + } + + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return ret; +} + + +const char pcb_acts_selectlayer[] = "SelectLayer(1..MAXLAYER|Silk|Rats)"; +const char pcb_acth_selectlayer[] = "Select which layer is the current layer."; + +/* %start-doc actions SelectLayer + +The specified layer becomes the currently active layer. It is made +visible if it is not already visible + +%end-doc */ + +static int pcb_act_SelectLayer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_layer_id_t lid; + + if (pcb_strcasecmp(argv[0], "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"); + } + else if (pcb_strcasecmp(argv[0], "rats") == 0) { + PCB->RatOn = PCB->RatDraw = 1; + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else { + PCB->RatDraw = 0; + pcb_layervis_change_group_vis(atoi(argv[0])-1, 1, 1); + } + + return 0; +} + + +const char pcb_acts_toggleview[] = "ToggleView(1..MAXLAYER)\n" "ToggleView(layername)\n" "ToggleView(Silk|Rats|Pins|Vias|Mask|BackSide)\n" "ToggleView(All, Open|Vis, Set|Clear|Toggle)"; +const char pcb_acth_toggleview[] = "Toggle the visibility of the specified layer or layer group."; + +/* %start-doc actions ToggleView + +If you pass an integer, that layer is specified by index (the first +layer is @code{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. + +%end-doc */ + +static int pcb_act_ToggleView(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_layer_id_t lid; + + if (argc < 1) + PCB_ACT_FAIL(toggleview); /* argv[0] is a must */ + + if (pcb_strcasecmp(argv[0], "all") == 0) { + pcb_bool_op_t open = PCB_BOOL_PRESERVE, vis = PCB_BOOL_PRESERVE, user = PCB_BOOL_PRESERVE; + if (argc < 3) + PCB_ACT_FAIL(toggleview); + user = pcb_str2boolop(argv[2]); + if (user == PCB_BOOL_INVALID) + PCB_ACT_FAIL(toggleview); + if (pcb_strcasecmp(argv[1], "open") == 0) + open = user; + else if (pcb_strcasecmp(argv[1], "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(argv[0], "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(argv[0], "rats") == 0) { + PCB->RatOn = !PCB->RatOn; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else if (pcb_strcasecmp(argv[0], "vias") == 0) { + PCB->ViaOn = !PCB->ViaOn; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else if ((pcb_strcasecmp(argv[0], "pins") == 0) || (pcb_strcasecmp(argv[0], "pads") == 0)) { + PCB->PinOn = !PCB->PinOn; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else if (pcb_strcasecmp(argv[0], "BackSide") == 0) { + PCB->InvisibleObjectsOn = !PCB->InvisibleObjectsOn; + pcb_gui->invalidate_all(); + pcb_event(PCB_EVENT_LAYERVIS_CHANGED, NULL); + } + else { + pcb_layervis_change_group_vis(atoi(argv[0])-1, -1, 0); + } + + return 1; +} + +pcb_hid_action_t gui_action_list[] = { + {"Display", 0, pcb_act_Display, + pcb_acth_Display, pcb_acts_Display} + , + {"CycleDrag", 0, pcb_act_CycleDrag, + pcb_acth_CycleDrag, pcb_acts_CycleDrag} + , + {"FullScreen", 0, pcb_act_FullScreen, + pcb_acth_FullScreen, pcb_acts_FullScreen} + , + {"MarkCrosshair", 0, pcb_act_MarkCrosshair, + pcb_acth_MarkCrosshair, pcb_acts_MarkCrosshair} + , + {"Message", 0, pcb_act_Message, + pcb_acth_Message, pcb_acts_Message} + , + {"Mode", 0, pcb_act_Mode, + pcb_acth_Mode, pcb_acts_Mode} + , + {"ToggleHideName", 0, pcb_act_ToggleHideName, + pcb_acth_ToggleHideName, pcb_acts_ToggleHideName} + , + {"SetSame", N_("Select item to use attributes from"), pcb_act_SetSame, + pcb_acth_SetSame, pcb_acts_SetSame} + , + {"RouteStyle", 0, pcb_act_RouteStyle, + pcb_acth_RouteStyle, pcb_acts_RouteStyle} + , + {"CreateMenu", 0, pcb_act_CreateMenu, + pcb_acth_CreateMenu, pcb_acts_CreateMenu} + , + {"RemoveMenu", 0, pcb_act_RemoveMenu, + pcb_acth_RemoveMenu, pcb_acts_RemoveMenu} + , + {"SelectLayer", 0, pcb_act_SelectLayer, + pcb_acth_selectlayer, pcb_acts_selectlayer} + , + {"SwitchHID", 0, pcb_act_SwitchHID, + pcb_acth_SwitchHID, pcb_acts_SwitchHID} + , + {"ToggleView", 0, pcb_act_ToggleView, + pcb_acth_toggleview, pcb_acts_toggleview} + , + {"PCBChanged", 0, pcb_act_PCBChanged, + pcb_acth_PCBChanged, pcb_acts_PCBChanged} + , + {"NetlistChanged", 0, pcb_act_NetlistChanged, + pcb_acth_NetlistChanged, pcb_acts_NetlistChanged} + , + {"RouteStylesChanged", 0, pcb_act_RouteStylesChanged, + pcb_acth_RouteStylesChanged, pcb_acts_RouteStylesChanged} + , + {"LibraryChanged", 0, pcb_act_LibraryChanged, + pcb_acth_LibraryChanged, pcb_acts_LibraryChanged} + , + {"Cursor", 0, pcb_act_Cursor, pcb_acth_cursor, pcb_acts_cursor} + , + {"EditLayer", 0, pcb_act_EditLayer, + pcb_acth_EditLayer, pcb_acts_EditLayer} + , + {"EditGroup", 0, pcb_act_EditGroup, + pcb_acth_EditGroup, pcb_acts_EditGroup} +}; + +PCB_REGISTER_ACTIONS(gui_action_list, NULL) Index: tags/1.2.7/src/heap.c =================================================================== --- tags/1.2.7/src/heap.c (nonexistent) +++ tags/1.2.7/src/heap.c (revision 13657) @@ -0,0 +1,226 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src/heap.h =================================================================== --- tags/1.2.7/src/heap.h (nonexistent) +++ tags/1.2.7/src/heap.h (revision 13657) @@ -0,0 +1,61 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src/hid.h =================================================================== --- tags/1.2.7/src/hid.h (nonexistent) +++ tags/1.2.7/src/hid.h (revision 13657) @@ -0,0 +1,648 @@ +#ifndef PCB_HID_H +#define PCB_HID_H + +#include + +#include "config.h" +#include "error.h" +#include "drc.h" +#include "global_typedefs.h" +#include "attrib.h" +#include "layer.h" +#include "layer_grp.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 default resolution (1/100 mil 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. + +*/ + +/* Like end cap styles. The cap *always* extends beyond the + coordinates given, by half the width of the line. Beveled ends can + be used to make octagonal pads by giving the same x,y coordinate + twice. */ +typedef enum { + Trace_Cap, /* This means we're drawing a trace, which has round caps. */ + Square_Cap, /* Square pins or pads. */ + Round_Cap, /* Round pins or round-ended pads, thermals. */ + Beveled_Cap /* Octagon pins or bevel-cornered pads. */ +} 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; + +/* 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. */ +typedef struct hid_gc_s *pcb_hid_gc_t; + +#define PCB_HIDCONCAT(a,b) a##b + +/* This is used to register the action callbacks (for menus and + whatnot). HID assumes the following actions are available for its + use: + SaveAs(filename); + Quit(); +*/ +typedef struct { + /* This is matched against action names in the GUI configuration */ + const char *name; + /* If this string is non-NULL, the action needs to know the X,Y + coordinates to act on, and this string may be used to prompt + the user to select a coordinate. If NULL, the coordinates may + be 0,0 if none are known. */ + const char *need_coord_msg; + /* Called when the action is triggered. If this function returns + non-zero, no further actions will be invoked for this key/mouse + event. */ + int (*trigger_cb) (int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); + /* Short description that sometimes accompanies the name. */ + const char *description; + /* Full allowed syntax; use \n to separate lines. */ + const char *syntax; +} pcb_hid_action_t; + +extern void pcb_hid_register_action(const pcb_hid_action_t *a, const char *cookie, int copy); + +extern void pcb_hid_register_actions(const pcb_hid_action_t *a, int, const char *cookie, int copy); +#define PCB_REGISTER_ACTIONS(a, cookie) PCB_HIDCONCAT(void register_,a) ()\ +{ pcb_hid_register_actions(a, sizeof(a)/sizeof(a[0]), cookie, 0); } + +/* Note that PCB expects the GUI to provide the following actions: + + LibraryChanged() + */ + +/* 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; + +/* DRC GUI Hooks */ +typedef struct { + int log_drc_overview; + int log_drc_violations; + void (*reset_drc_dialog_message) (void); + void (*append_drc_violation) (pcb_drc_violation_t * violation); + int (*throw_drc_dialog) (void); +} pcb_hid_drc_gui_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 */ + 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_CANCEL = 0, + PCB_HID_ATTR_EV_OK = 1, + PCB_HID_ATTR_EV_WINCLOSE +} pcb_hid_attr_ev_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; + + /* 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; + + + /* If set, draws holes after copper, silk and mask, to make sure it + punches through everything. */ + unsigned holes_after:1; + + /* lesstif allows positive AND negative drawing in HID_MASK_CLEAR. + gtk only allows negative drawing. + using the mask is to get rat transparency */ + unsigned can_mask_clear_rats:1; + + /* Always draw layers in compositing mode - no base layer */ + unsigned force_compositing: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); + + /* 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. */ + void (*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); 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, pcb_layer_id_t layer, unsigned int flags, int is_empty); + + /* Tell the GUI the layer last selected has been finished with. */ + void (*end_layer) (void); + + /* Drawing Functions. Coordinates and distances are ALWAYS in PCB's + default coordinates (1/100 mil at the time this comment was + written). Angles are always in degrees, with 0 being "right" + (positive X) and 90 being "up" (positive Y). */ + + /* 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. */ + void (*render_burst)(pcb_burst_op_t op, const pcb_box_t *screen); + + /* Sets a color. Names can be like "red" or "#rrggbb" or special + names like "erase". *Always* use the "erase" color for removing + ink (like polygon reliefs or thermals), as you cannot rely on + knowing the background color or special needs of the HID. Always + use the "drill" color to draw holes. 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 char *name_); + + /* 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_pcb_pad) (pcb_hid_gc_t gc_, pcb_pad_t * pad, pcb_bool clip, pcb_bool mask); + void (*thindraw_pcb_pad) (pcb_hid_gc_t gc_, pcb_pad_t * pad, pcb_bool clip, pcb_bool mask); + void (*fill_pcb_pv) (pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask); + void (*thindraw_pcb_pv) (pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask); + 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_); + + /* 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) (int x_, int 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_); + + /* Causes func_ to be called in the mainloop prior to blocking */ + pcb_hidval_t(*add_block_hook) (void (*func_) (pcb_hidval_t data_), pcb_hidval_t data_); + /* Use this to stop a mainloop block hook. */ + void (*stop_block_hook) (pcb_hidval_t block_hook_); + + /* Various dialogs */ + + /* Logs a message to the log window. */ + void (*log) (const char *fmt_, ...); + void (*logv) (enum pcb_message_level, const char *fmt_, va_list args_); + + /* A generic yes/no dialog. Returns zero if the cancel button is + pressed, one for the OK button. If you specify alternate labels + for ..., they are used instead of the default OK/Cancel ones, and + the return value is the index of the label chosen. You MUST pass + NULL as the last parameter to this. */ + int (*confirm_dialog) (const char *msg_, ...); + + /* A close confirmation dialog for unsaved pages, for example, with + options "Close without saving", "Cancel" and "Save". Returns zero + if the close is cancelled, or one if it should proceed. The HID + is responsible for any "Save" action the user may wish before + confirming the close. + */ + int (*close_confirm_dialog) (); +#define HID_CLOSE_CONFIRM_CANCEL 0 +#define HID_CLOSE_CONFIRM_OK 1 + + /* Just prints text. */ + void (*report_dialog) (const char *title_, const char *msg_); + + /* 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 like "Enter value:". Returns NULL on cancel. */ + char *(*prompt_for) (const char *msg_, const char *default_string_); + + /* 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. */ +#define HID_FILESELECT_READ 0x01 + + /* 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. + */ +#define HID_FILESELECT_MAY_NOT_EXIST 0x02 + + /* The call is supposed to return a file template (for gerber + output for example) instead of an actual file. Only used when + writing. + */ +#define HID_FILESELECT_IS_TEMPLATE 0x04 + + /* 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. + * + * 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 of the HID_FILESELECT defines above + */ + + char *(*fileselect) (const char *title_, const char *descr_, + const char *default_file_, const char *default_ext_, const char *history_tag_, int flags_); + + /* A generic dialog to ask for a set of attributes. If n_attrs_ is + zero, attrs_(.name) must be NULL terminated. 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 + descr_ (if not NULL) can be a longer description of what the + attributes are used for. 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. + */ + int (*attribute_dialog)(pcb_hid_attribute_t * attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, const char *descr_, void *caller_data); + + /* The same API in 3 stages: */ + void *(*attr_dlg_new)(pcb_hid_attribute_t *attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, const char *descr_, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev)); /* returns hid_ctx */ + int (*attr_dlg_run)(void *hid_ctx); + 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); + + + /* This causes a second window to display, which only shows the + selected item_. The expose callback is called twice; once to size + the extents of the item, and once to draw it. To pass magic + values, pass the address of a variable created for this + purpose. */ + void (*show_item) (void *item_); + + /* Something to alert the user. */ + void (*beep) (void); + + /* Used by optimizers and autorouter to show progress to the user. + Pass all zeros to flush display and remove any dialogs. + Returns nonzero if the user wishes to cancel the operation. */ + int (*progress) (int so_far_, int total_, const char *message_); + + pcb_hid_drc_gui_t *drc_gui; + + void (*edit_attributes) (const char *owner, pcb_attribute_list_t * attrlist_); + + /* Debug drawing support. These APIs must be implemented (non NULL), + * but they do not have to be functional. request_debug_draw can + * return NULL to indicate debug drawing is not permitted. + * + * Debug drawing is not guaranteed to be re-entrant. + * The caller must not nest requests for debug drawing. + */ + + /* Request permission for debug drawing + * + * Returns a HID pointer which should be used rather than the global + * gui-> for making drawing calls. If the return value is NULL, then + * permission has been denied, and the drawing must not continue. + */ + pcb_hid_t *(*request_debug_draw) (void); + + /* Flush pending drawing to the screen + * + * May be implemented as a NOOP if the GUI has chosen to send the + * debug drawing directly to the screen. + */ + void (*flush_debug_draw) (void); + + /* When finished, the user must inform the GUI to clean up resources + * + * Any remaining rendering will be flushed to the screen. + */ + void (*finish_debug_draw) (void); + + /* 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, mnemonic, 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 char *action, const char *mnemonic, const char *accel, const char *tip, const char *cookie); + + /* Removes a menu recursively */ + int (*remove_menu) (const char *menu_path); + + /* 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); + + /*** PROPEDIT (optional) ****/ + /* Optional: start a propedit session: a series of propedit calls will follow + Return 0 on success; non-zero aborts the session. + */ + int (*propedit_start)(void *pe, int num_props, const char *(*query)(void *pe, const char *cmd, const char *key, const char *val, int idx)); + + /* Optional: end a propedit session: all data has been sent, no more; this call + should present and run the user dialog and should return, only when the + propedit section can be closed. */ + void (*propedit_end)(void *pe); + + /* Optional: registers a new property + Returns a prop context passed with each value + */ + void *(*propedit_add_prop)(void *pe, const char *propname, int is_mutable, int num_vals); + + /* Optional: registers a new value for a property */ + void (*propedit_add_value)(void *pe, const char *propname, void *propctx, const char *value, int repeat_cnt); + + /* Optional: registers statistical info for a property */ + void (*propedit_add_stat)(void *pe, const char *propname, void *propctx, const char *most_common, const char *min, const char *max, const char *avg); +}; + +/* 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 elements (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_dialog_draw_t)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e); + +struct pcb_hid_expose_ctx_s { + pcb_box_t view; + unsigned force:1; /* draw even if layer set fails */ + union { + pcb_layer_id_t layer_id; + pcb_any_obj_t *obj; + } content; + + /* for PCB_LYT_DIALOG */ + pcb_hid_dialog_draw_t dialog_draw; +}; + +typedef void (*pcb_hid_expose_t)(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *ctx); + +/* 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); + +/* Pinout preview expose: draws an element; content.elem is used */ +void pcb_hid_expose_pinout(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *element); + + +/* Layer preview expose: draws a single layer; content.layer_id is used */ +void pcb_hid_expose_layer(pcb_hid_t *hid, const pcb_hid_expose_ctx_t *ly); + + +/* 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_hid_action_t that is being + called. The action launcher sets and unsets this variable. */ +extern const pcb_hid_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; + +/* Inits and uninits the whole action framework */ +void pcb_hid_actions_init(void); +void pcb_hid_actions_uninit(void); + +#endif Index: tags/1.2.7/src/hid_actions.c =================================================================== --- tags/1.2.7/src/hid_actions.c (nonexistent) +++ tags/1.2.7/src/hid_actions.c (revision 13657) @@ -0,0 +1,457 @@ +#include "config.h" +#include "conf_core.h" + +#include + +#include +#include + +#include "error.h" +#include "event.h" +#include "hid_actions.h" +#include "compat_misc.h" +#include "compat_nls.h" + +static htsp_t *all_actions = NULL; +const pcb_hid_action_t *pcb_current_action = NULL; + +static const char *check_action_name(const char *s) +{ + while (*s) + if (isspace((int) *s++) || *s == '(') + return (s - 1); + return NULL; +} + +typedef struct { + const char *cookie; + const pcb_hid_action_t *action; +} hid_cookie_action_t; + +void pcb_hid_register_actions(const pcb_hid_action_t * a, int n, const char *cookie, int copy) +{ + int i; + hid_cookie_action_t *ca; + + if (all_actions == NULL) + all_actions = htsp_alloc(strhash_case, strkeyeq_case); + + for (i = 0; i < n; i++) { + 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; + } + if (htsp_get(all_actions, a[i].name) != NULL) { + pcb_message(PCB_MSG_ERROR, _("ERROR! Invalid action name, " "action \"%s\" is already registered.\n"), a[i].name); + continue; + } + ca = malloc(sizeof(hid_cookie_action_t)); + ca->cookie = cookie; + ca->action = a+i; + htsp_set(all_actions, pcb_strdup(a[i].name), ca); + } +} + +void pcb_hid_register_action(const pcb_hid_action_t * a, const char *cookie, int copy) +{ + pcb_hid_register_actions(a, 1, cookie, copy); +} + +void pcb_hid_remove_actions(const pcb_hid_action_t * a, int n) +{ + int i; + + if (all_actions == NULL) + return; + + for (i = 0; i < n; i++) { + htsp_entry_t *e; + e = htsp_popentry(all_actions, a[i].name); + free(e->key); + free(e->value); + } +} + +void pcb_hid_remove_actions_by_cookie(const char *cookie) +{ + htsp_entry_t *e; + + if (all_actions == NULL) + return; + + /* Slow linear search - probably OK, this will run only on uninit */ + for (e = htsp_first(all_actions); e; e = htsp_next(all_actions, e)) { + hid_cookie_action_t *ca = e->value; + if (ca->cookie == cookie) { + htsp_pop(all_actions, e->key); + free(e->key); + free(e->value); + } + } +} + +void pcb_hid_remove_action(const pcb_hid_action_t * a) +{ + htsp_entry_t *e; + + if (all_actions == NULL) + return; + + e = htsp_popentry(all_actions, a->name); + if (e != NULL) { + free(e->key); + free(e->value); + } +} + +const pcb_hid_action_t *pcb_hid_find_action(const char *name) +{ + hid_cookie_action_t *ca; + + if ((name == NULL) && (all_actions == NULL)) + return 0; + + ca = htsp_get(all_actions, (char *) name); + + if (ca) + return ca->action; + + pcb_message(PCB_MSG_ERROR, "unknown action `%s'\n", name); + return 0; +} + +void pcb_print_actions() +{ + htsp_entry_t *e; + + fprintf(stderr, "Registered Actions:\n"); + for (e = htsp_first(all_actions); e; e = htsp_next(all_actions, e)) { + hid_cookie_action_t *ca = e->value; + 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(all_actions); e; e = htsp_next(all_actions, e)) { + hid_cookie_action_t *ca = e->value; + const char *desc = ca->action->description; + const char *synt = ca->action->syntax; + + desc = desc ? desc : ""; + synt = synt ? synt : ""; + + printf("A%s\n", ca->action->name); + dump_string('D', desc); + dump_string('S', synt); + } +} + +int pcb_hid_action(const char *name) +{ + return pcb_hid_actionv(name, 0, 0); +} + +int pcb_hid_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_hid_actionv(name, argc, argv); +} + +int pcb_hid_actionv_(const pcb_hid_action_t *a, int argc, const char **argv) +{ + pcb_coord_t x = 0, y = 0; + int i, ret; + const pcb_hid_action_t *old_action; + + if (a->need_coord_msg) + pcb_gui->get_coords(_(a->need_coord_msg), &x, &y); + + if (conf_core.rc.verbose) { + printf("Action: \033[34m%s(", a->name); + for (i = 0; i < argc; i++) + printf("%s%s", i ? "," : "", argv[i]); + printf(")\033[0m\n"); + } + + old_action = pcb_current_action; + pcb_current_action = a; + ret = pcb_current_action->trigger_cb(argc, argv, x, y); + pcb_current_action = old_action; + + return ret; +} + +int pcb_hid_actionv(const char *name, int argc, const char **argv) +{ + const pcb_hid_action_t *a; + + if (!name) + return 1; + + a = pcb_hid_find_action(name); + if (!a) { + 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 ? ", " : "", argv[i]); + pcb_message(PCB_MSG_ERROR, ")\n"); + return 1; + } + return pcb_hid_actionv_(a, argc, argv); +} + +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) { + retcode = pcb_hid_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_hid_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; +} + +int pcb_hid_parse_command(const char *str_) +{ + pcb_event(PCB_EVENT_CLI_ENTER, "s", str_); + return hid_parse_actionstring(str_, pcb_false); +} + +int pcb_hid_parse_actions(const char *str_) +{ + return hid_parse_actionstring(str_, pcb_true); +} + +void pcb_hid_actions_init(void) +{ + +} + +void pcb_hid_actions_uninit(void) +{ + htsp_entry_t *e; + + if (all_actions == NULL) + return; + + for (e = htsp_first(all_actions); e; e = htsp_next(all_actions, e)) { + hid_cookie_action_t *ca = e->value; + if (ca->cookie != NULL) + fprintf(stderr, "WARNING: hid_actions_uninit: action '%s' with cookie '%s' left registered, check your plugins!\n", e->key, ca->cookie); + free(e->key); + free(e->value); + } + + htsp_free(all_actions); + all_actions = NULL; +} + +/* trick for the doc extractor */ +#define static + +/* %start-doc actions 00macros + +@macro hidaction + +This is one of a number of actions which are part of the HID +interface. The core functions use these actions to tell the current +GUI when to change the presented information in response to changes +that the GUI may not know about. The user normally does not invoke +these directly. + +@end macro + +%end-doc */ + +static const char layerschanged_syntax[] = "LayersChanged()"; +static const char layerschanged_help[] = "Tells the GUI that the layers have changed."; + +/* %start-doc actions LayersChanged + +This includes layer names, colors, stacking order, visibility, etc. + +@hidaction + +%end-doc */ + Index: tags/1.2.7/src/hid_actions.h =================================================================== --- tags/1.2.7/src/hid_actions.h (nonexistent) +++ tags/1.2.7/src/hid_actions.h (revision 13657) @@ -0,0 +1,37 @@ +#ifndef PCB_HID_ACTIONS_H +#define PCB_HID_ACTIONS_H + +#include "hid.h" + +/* These are called from main_act.c */ +void pcb_print_actions(void); +void pcb_dump_actions(void); + + +/* HID internal interfaces. These may ONLY be called from the HID + modules, not from the common PCB code. */ + +const pcb_hid_action_t *pcb_hid_find_action(const char *name); + +extern void pcb_hid_remove_actions(const pcb_hid_action_t * a, int n); +extern void pcb_hid_remove_action(const pcb_hid_action_t * a); +extern void pcb_hid_remove_actions_by_cookie(const char *cookie); + +int pcb_hid_action(const char *action_); +int pcb_hid_actionl(const char *action_, ...); /* NULL terminated */ +int pcb_hid_actionv(const char *action_, int argc_, const char **argv_); +int pcb_hid_actionv_(const pcb_hid_action_t *a, int argc, const char **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. Returns nonzero if the action handler(s) + return nonzero. */ +int pcb_hid_parse_command(const char *str_); + +/* Parse the given string into action calls, and call + hid_actionv for each action found. Accepts only + "action(arg1, arg2)" */ +int pcb_hid_parse_actions(const char *str_); + +#endif Index: tags/1.2.7/src/hid_attrib.c =================================================================== --- tags/1.2.7/src/hid_attrib.c (nonexistent) +++ tags/1.2.7/src/hid_attrib.c (revision 13657) @@ -0,0 +1,241 @@ +#include "config.h" +#include "hid_attrib.h" +#include "misc_util.h" +#include "pcb-printf.h" + +pcb_hid_attr_node_t *hid_attr_nodes = 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; + } +} + +void pcb_hid_parse_command_line(int *argc, char ***argv) +{ + pcb_hid_attr_node_t *ha; + int i, e, ok; + + 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 = 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 && (*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 = (*argv)[1]; + else + a->default_val.str_value = (*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 = (*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]); + exit(1); + got_match:; + } +} + +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_atrdlg_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; +} Index: tags/1.2.7/src/hid_attrib.h =================================================================== --- tags/1.2.7/src/hid_attrib.h (nonexistent) +++ tags/1.2.7/src/hid_attrib.h (revision 13657) @@ -0,0 +1,99 @@ +#ifndef PCB_HID_ATTRIB_H +#define PCB_HID_ATTRIB_H + +#include "hid.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; + void (*func)(); +}; + +typedef enum pcb_hatt_compflags_e { + PCB_HATF_FRAME = 1, /* box/table has a visible frame around it */ + PCB_HATF_LABEL = 2, /* direct children print label */ + PCB_HATF_SCROLL = 4 /* box/table is scrollable */ +} 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 */ + + /* groups (e.g. boxes) */ + PCB_HATT_BEGIN_HBOX, /* NOTE: PCB_HATT_IS_COMPOSITE() depends on it */ + PCB_HATT_BEGIN_VBOX, + PCB_HATT_BEGIN_TABLE, /* min_val is the number of columns */ + 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 max_val +#define pcb_hatt_table_cols min_val + +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. */ + 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; + + /* Advanced API: may not be available in all HIDs; supported by hid_gtk */ + 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 *user_data; /* ignored; the caller is free to use it */ +}; + +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_atrdlg_num_children(pcb_hid_attribute_t *attrs, int start_from, int n_attrs); + +#endif Index: tags/1.2.7/src/hid_cfg.c =================================================================== --- tags/1.2.7/src/hid_cfg.c (nonexistent) +++ tags/1.2.7/src/hid_cfg.c (revision 13657) @@ -0,0 +1,513 @@ +/* + * 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. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hid_cfg.h" +#include "error.h" +#include "paths.h" +#include "safe_fs.h" +#include "compat_misc.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 char *action; + const char *mnemonic; + const char *accel; + const char *tip; + const char *cookie; + int target_level; + int err; +} 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; + +/* 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, name, "dyn", "1", "m", "cookie", cmc->cookie, cmc->mnemonic, "a", cmc->accel, "tip", cmc->tip, ((cmc->action != NULL) ? "action": NULL), cmc->action, NULL); + if (node != NULL) + cmc->err = 0; + } + else + node = pcb_hid_cfg_create_hash_node(psub, name, "dyn", "1", "cookie", cmc->cookie, NULL); + + if (node == NULL) + return NULL; + + if ((rel_level != cmc->target_level) || (cmc->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->cb(cmc->cb_ctx, path, name, (rel_level == 1), cmc->parent, node) != 0) { + cmc->err = -1; + return NULL; + } + } + cmc->parent = node; + return node; +} + +int pcb_hid_cfg_create_menu(pcb_hid_cfg_t *hr, const char *path, const char *action, const char *mnemonic, const char *accel, const char *tip, const char *cookie, 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.action = action; + cmc.mnemonic = mnemonic; + cmc.accel = accel; + cmc.tip = tip; + cmc.cookie = cookie; + cmc.err = -1; + + /* 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; +} + + +static int hid_cfg_remove_menu_(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 (hid_cfg_remove_menu_(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(pcb_hid_cfg_t *hr, const char *path, int (*gui_remove)(void *ctx, lht_node_t *nd), void *ctx) +{ + return hid_cfg_remove_menu_(hr, pcb_hid_cfg_get_menu_at(hr, NULL, path, NULL, NULL), 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; + + 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); + 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_message(PCB_MSG_INFO, "Loaded menu file '%s'\n", *p); + } + free(*p); + } + free(paths); + } + else + doc = pcb_hid_cfg_load_lht(fn); + + if (doc == NULL) + doc = pcb_hid_cfg_load_str(embedded_fallback); + 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); + 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, save; + 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); + + if (level > 0) + *end = ':'; + else + *end = '\0'; + end++; + save = *end; + *end = '\0'; + + curr = lht_tree_path_(hr->doc, curr, next_seg, 1, 0, &err); + if (cb != NULL) { + end[-1] = '\0'; + curr = cb(ctx, curr, path, level); + } + + *end = save; + 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++; + } + + 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_MNEMONIC: fieldstr = "m"; 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; +/* case MF_RADIO: fieldstr = "radio"; 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, const char *name, ...) +{ + lht_node_t *n; + va_list ap; + + if ((parent != NULL) && (parent->type != LHT_LIST)) + return NULL; + + n = lht_dom_node_alloc(LHT_HASH, name); + if (parent != NULL) + 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; +} + +/* extern char hid_cfg_error_shared[]; */ +void pcb_hid_cfg_error(const lht_node_t *node, const char *fmt, ...) +{ + char *end; + va_list ap; + + end = hid_cfg_error_shared + sprintf(hid_cfg_error_shared, "Error in lihata node %s:%d.%d:", node->file_name, node->line, node->col); + va_start(ap, fmt); + end += vsprintf(end, fmt, ap); + va_end(ap); + pcb_message(PCB_MSG_ERROR, hid_cfg_error_shared); +} Index: tags/1.2.7/src/hid_cfg.h =================================================================== --- tags/1.2.7/src/hid_cfg.h (nonexistent) +++ tags/1.2.7/src/hid_cfg.h (revision 13657) @@ -0,0 +1,114 @@ +/* + * 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. + * + */ + +/* Helpers for loading and handling lihata HID config files */ + +#ifndef PCB_HID_CFG_H +#define PCB_HID_CFG_H + +#include +#include + +typedef struct pcb_hid_cfg_s { + lht_doc_t *doc; +} pcb_hid_cfg_t; + +/* 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 *menu_item); +int pcb_hid_cfg_create_menu(pcb_hid_cfg_t *hr, const char *path, const char *action, const char *mnemonic, const char *accel, const char *tip, const char *cookie, 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); + +/* 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); + + +/* Fields are retrieved using this enum so that HIDs don't need to hardwire + lihata node names */ +typedef enum { + PCB_MF_ACCELERATOR, + PCB_MF_MNEMONIC, + 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 +/* MF_RADIO*/ +} 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. */ +lht_node_t *pcb_hid_cfg_create_hash_node(lht_node_t *parent, 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/1.2.7/src/hid_cfg_action.c =================================================================== --- tags/1.2.7/src/hid_cfg_action.c (nonexistent) +++ tags/1.2.7/src/hid_cfg_action.c (revision 13657) @@ -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. + * + */ + +#include "config.h" +#include "hid_cfg_action.h" +#include "hid_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_hid_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_hid_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/1.2.7/src/hid_cfg_action.h =================================================================== --- tags/1.2.7/src/hid_cfg_action.h (nonexistent) +++ tags/1.2.7/src/hid_cfg_action.h (revision 13657) @@ -0,0 +1,27 @@ +/* + * 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. + * + */ + + +#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/1.2.7/src/hid_cfg_input.c =================================================================== --- tags/1.2.7/src/hid_cfg_input.c (nonexistent) +++ tags/1.2.7/src/hid_cfg_input.c (revision 13657) @@ -0,0 +1,518 @@ +/* + * 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. + * + */ + +#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" + +/* 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_hid_cfg_action(find_best_action(mouse, button_and_mask)); + pcb_event(PCB_EVENT_USER_INPUT_POST, NULL); +} + + +/************************** 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) +{ +#warning 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) +{ + 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)) + 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) + 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 char *curr, *next, *last, *k, *desc1; + 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'\n", keydesc); + return -1; + } + len -= k-last; + desc1 = k; + 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\n", k-1); + return -1; + } + + if ((key_raws[slen] == 0) && (key_trs[slen] == 0)) { + char *s; + s = malloc(len+1); + memcpy(s, desc1, k-desc1); + s[len] = '\0'; + pcb_message(PCB_MSG_ERROR, "Unrecognised key symbol in key description: %s\n", s); + 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; + + slen = parse_keydesc(km, keydesc, mods, key_raws, key_trs, HIDCFG_MAX_KEYSEQ_LEN); + 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); + if (s == NULL) { + printf(" ERROR\n"); +#warning 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_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; +} + +static void gen_accel(gds_t *s, pcb_hid_cfg_keys_t *km, const char *keydesc, int *cnt, const char *sep) +{ + 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); + 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); + 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); + } + } + 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); + + /* 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) { + int len = *seq_len; + (*seq_len) = 0; + return len; + } + + return 0; +} + +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; +} Index: tags/1.2.7/src/hid_cfg_input.h =================================================================== --- tags/1.2.7/src/hid_cfg_input.h (nonexistent) +++ tags/1.2.7/src/hid_cfg_input.h (revision 13657) @@ -0,0 +1,149 @@ +#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); + + +/************************** 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() */ +} 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 */ +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); + +/* 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, 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, 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, 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_keyseq_t **seq, int seq_len); + + +#endif Index: tags/1.2.7/src/hid_color.c =================================================================== --- tags/1.2.7/src/hid_color.c (nonexistent) +++ tags/1.2.7/src/hid_color.c (revision 13657) @@ -0,0 +1,58 @@ +#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/1.2.7/src/hid_color.h =================================================================== --- tags/1.2.7/src/hid_color.h (nonexistent) +++ tags/1.2.7/src/hid_color.h (revision 13657) @@ -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/1.2.7/src/hid_dad.h =================================================================== --- tags/1.2.7/src/hid_dad.h (nonexistent) +++ tags/1.2.7/src/hid_dad.h (revision 13657) @@ -0,0 +1,237 @@ +/* + * 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. + * + */ + +#ifndef PCB_HID_DAD_H +#define PCB_HID_DAD_H + +#include +#include +#include "compat_misc.h" +#include "hid_attrib.h" +#include "pcb-printf.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 ## _len = 0; \ + int table ## _alloced = 0; \ + void *table ## _hid_ctx = NULL; \ + +#define PCB_DAD_DECL_NOINIT(table) \ + pcb_hid_attribute_t *table; \ + pcb_hid_attr_val_t *table ## _result; \ + int table ## _len; \ + int table ## _alloced; \ + void *table ## _hid_ctx; \ + +/* Free all resources allocated by DAD macros for table */ +#define PCB_DAD_FREE(table) \ +do { \ + int __n__; \ + if (table ## _hid_ctx != 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); \ +} while(0) + +#define PCB_DAD_NEW(table, title, descr, caller_data, modal, ev_cb) \ +do { \ + if (table ## _result == NULL) \ + PCB_DAD_ALLOC_RESULT(table); \ + table ## _hid_ctx = pcb_gui->attr_dlg_new(table, table ## _len, table ## _result, title, descr, caller_data, modal, ev_cb); \ +} while(0) + +#define PCB_DAD_RUN(table) pcb_gui->attr_dlg_run(table ## _hid_ctx) + +#define PCB_DAD_AUTORUN(table, title, descr, caller_data) \ +do { \ + if (table ## _result == NULL) \ + PCB_DAD_ALLOC_RESULT(table); \ + pcb_gui->attribute_dialog(table, table ## _len, table ## _result, title, descr, caller_data); \ +} 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_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) + +#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_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_BUTTON(table, text) \ +do { \ + PCB_DAD_ALLOC(table, PCB_HATT_BUTTON); \ + table[table ## _len - 1].default_val.str_value = text; \ +} 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_DEFAULT(table, val) PCB_DAD_SET_ATTR_FIELD_VAL(table, default_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_HELP(table, val) PCB_DAD_SET_ATTR_FIELD(table, help_text, val) + +/* 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) ***/ +#define PCB_DAD_ALLOC(table, item_type) \ + do { \ + if (table ## _len >= table ## _alloced) { \ + table ## _alloced += 16; \ + table = realloc(table, sizeof(table[0]) * table ## _alloced); \ + } \ + 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_COORD: \ + case PCB_HATT_UNIT: \ + table[table ## _len - 1].field.int_value = (int)val; \ + break; \ + case PCB_HATT_REAL: \ + table[table ## _len - 1].field.real_value = (double)val; \ + break; \ + case PCB_HATT_STRING: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + table[table ## _len - 1].field.str_value = (char *)val; \ + break; \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_END: \ + assert(0); \ + } \ +} while(0) + +#define PCB_DAD_FREE_FIELD(table, field) \ +do { \ + switch(table[table ## _len - 1].type) { \ + case PCB_HATT_LABEL: \ + free((char *)table[table ## _len - 1].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_STRING: \ + case PCB_HATT_PATH: \ + case PCB_HATT_BUTTON: \ + break; \ + case PCB_HATT_BEGIN_HBOX: \ + case PCB_HATT_BEGIN_VBOX: \ + case PCB_HATT_BEGIN_TABLE: \ + case PCB_HATT_END: \ + 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) + +#endif Index: tags/1.2.7/src/hid_draw_helpers.c =================================================================== --- tags/1.2.7/src/hid_draw_helpers.c (nonexistent) +++ tags/1.2.7/src/hid_draw_helpers.c (revision 13657) @@ -0,0 +1,445 @@ +#include "config.h" +#include "hid.h" +#include "polygon.h" +#include "macro.h" + +#include "obj_pinvia.h" +#include "obj_pad.h" +#include "obj_poly.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; + pcb_coord_t this_x, this_y; + + pcb_gui->set_line_width(gc, 0); + pcb_gui->set_line_cap(gc, Round_Cap); + + /* 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; + + do { + this_x = v->point[0]; + this_y = v->point[1]; + + 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; + + 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_thindraw_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + pcb_coord_t w = clear ? (mask ? pad->Mask : pad->Thickness + pad->Clearance) + : pad->Thickness; + pcb_coord_t x1, y1, x2, y2; + pcb_coord_t t = w / 2; + x1 = pad->Point1.X; + y1 = pad->Point1.Y; + x2 = pad->Point2.X; + y2 = pad->Point2.Y; + if (x1 > x2 || y1 > y2) { + pcb_coord_t temp_x = x1; + pcb_coord_t temp_y = y1; + x1 = x2; + x2 = temp_x; + y1 = y2; + y2 = temp_y; + } + pcb_gui->set_line_cap(gc, Round_Cap); + pcb_gui->set_line_width(gc, 0); + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad)) { + /* slanted square pad */ + double tx, ty, theta; + + if (x1 == x2 && y1 == y2) + theta = 0; + else + theta = atan2(y2 - y1, x2 - x1); + + /* T is a vector half a thickness long, in the direction of + one of the corners. */ + tx = t * cos(theta + M_PI / 4) * sqrt(2.0); + ty = t * sin(theta + M_PI / 4) * sqrt(2.0); + + pcb_gui->draw_line(gc, x1 - tx, y1 - ty, x2 + ty, y2 - tx); + pcb_gui->draw_line(gc, x2 + ty, y2 - tx, x2 + tx, y2 + ty); + pcb_gui->draw_line(gc, x2 + tx, y2 + ty, x1 - ty, y1 + tx); + pcb_gui->draw_line(gc, x1 - ty, y1 + tx, x1 - tx, y1 - ty); + } + else if (x1 == x2 && y1 == y2) { + pcb_gui->draw_arc(gc, x1, y1, t, t, 0, 360); + } + else { + /* Slanted round-end pads. */ + pcb_coord_t dx, dy, ox, oy; + double h; + + dx = x2 - x1; + dy = y2 - y1; + h = t / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + ox = dy * h + 0.5 * SGN(dy); + oy = -(dx * h + 0.5 * SGN(dx)); + + pcb_gui->draw_line(gc, x1 + ox, y1 + oy, x2 + ox, y2 + oy); + + if (labs(ox) >= pcb_pixel_slop || coord_abs(oy) >= pcb_pixel_slop) { + pcb_angle_t angle = atan2(dx, dy) * 57.295779; + pcb_gui->draw_line(gc, x1 - ox, y1 - oy, x2 - ox, y2 - oy); + pcb_gui->draw_arc(gc, x1, y1, t, t, angle - 180, 180); + pcb_gui->draw_arc(gc, x2, y2, t, t, angle, 180); + } + } +} + +void pcb_dhlp_fill_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + pcb_coord_t w = clear ? (mask ? pad->Mask : pad->Thickness + pad->Clearance) + : pad->Thickness; + + if (pad->Point1.X == pad->Point2.X && pad->Point1.Y == pad->Point2.Y) { + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad)) { + pcb_coord_t l, r, t, b; + l = pad->Point1.X - w / 2; + b = pad->Point1.Y - w / 2; + r = l + w; + t = b + w; + pcb_gui->fill_rect(gc, l, b, r, t); + } + else { + pcb_gui->fill_circle(gc, pad->Point1.X, pad->Point1.Y, w / 2); + } + } + else { + pcb_gui->set_line_cap(gc, PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad) ? Square_Cap : Round_Cap); + pcb_gui->set_line_width(gc, w); + + pcb_gui->draw_line(gc, pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y); + } +} + +/* --------------------------------------------------------------------------- + * draws one polygon + * x and y are already in display coordinates + * the points are numbered: + * + * 5 --- 6 + * / \ + * 4 7 + * | | + * 3 0 + * \ / + * 2 --- 1 + */ + +typedef struct { + double X, Y; +} FloatPolyType; + +static void draw_square_pin_poly(pcb_hid_gc_t gc, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t thin_draw, int style) +{ + static FloatPolyType p[8] = { + {0.5, -PCB_TAN_22_5_DEGREE_2}, + {PCB_TAN_22_5_DEGREE_2, -0.5}, + {-PCB_TAN_22_5_DEGREE_2, -0.5}, + {-0.5, -PCB_TAN_22_5_DEGREE_2}, + {-0.5, PCB_TAN_22_5_DEGREE_2}, + {-PCB_TAN_22_5_DEGREE_2, 0.5}, + {PCB_TAN_22_5_DEGREE_2, 0.5}, + {0.5, PCB_TAN_22_5_DEGREE_2} + }; + static int special_size = 0; + static int scaled_x[8]; + static int scaled_y[8]; + pcb_coord_t polygon_x[9]; + pcb_coord_t polygon_y[9]; + double xm[8], ym[8]; + int i; + + pcb_poly_square_pin_factors(style, xm, ym); + + if (Thickness != special_size) { + special_size = Thickness; + for (i = 0; i < 8; i++) { + scaled_x[i] = p[i].X * special_size; + scaled_y[i] = p[i].Y * special_size; + } + } + /* add line offset */ + for (i = 0; i < 8; i++) { + polygon_x[i] = X + scaled_x[i] * xm[i]; + polygon_y[i] = Y + scaled_y[i] * ym[i]; + } + + if (thin_draw) { + int i; + pcb_gui->set_line_cap(gc, Round_Cap); + pcb_gui->set_line_width(gc, 0); + polygon_x[8] = X + scaled_x[0] * xm[0]; + polygon_y[8] = Y + scaled_y[0] * ym[0]; + for (i = 0; i < 8; i++) + pcb_gui->draw_line(gc, polygon_x[i], polygon_y[i], polygon_x[i + 1], polygon_y[i + 1]); + } + else + pcb_gui->fill_polygon(gc, 8, polygon_x, polygon_y); +} + +static void draw_octagon_poly(pcb_hid_gc_t gc, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t thin_draw) +{ + draw_square_pin_poly(gc, X, Y, Thickness, thin_draw, 17); +} + + +void pcb_dhlp_fill_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask) +{ + pcb_coord_t w = mask ? pv->Mask : pv->Thickness; + pcb_coord_t r = w / 2; + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + if (mask) + pcb_gui->fill_circle(bg_gc, pv->X, pv->Y, r); + if (drawHole) { + pcb_gui->fill_circle(bg_gc, pv->X, pv->Y, r); + pcb_gui->set_line_cap(fg_gc, Round_Cap); + pcb_gui->set_line_width(fg_gc, 0); + pcb_gui->draw_arc(fg_gc, pv->X, pv->Y, r, r, 0, 360); + } + return; + } + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pv)) { + /* use the original code for now */ + if ((PCB_FLAG_SQUARE_GET(pv) == 0) || (PCB_FLAG_SQUARE_GET(pv) == 1)) { + pcb_coord_t l = pv->X - r; + pcb_coord_t b = pv->Y - r; + pcb_coord_t r = l + w; + pcb_coord_t t = b + w; + pcb_gui->fill_rect(fg_gc, l, b, r, t); + } + else + draw_square_pin_poly(fg_gc, pv->X, pv->Y, w, pcb_false, PCB_FLAG_SQUARE_GET(pv)); + } + else if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pv)) + draw_octagon_poly(fg_gc, pv->X, pv->Y, w, pcb_false); + else /* draw a round pin or via */ + pcb_gui->fill_circle(fg_gc, pv->X, pv->Y, r); + + /* and the drilling hole (which is always round) */ + if (drawHole) + pcb_gui->fill_circle(bg_gc, pv->X, pv->Y, pv->DrillingHole / 2); +} + +void pcb_dhlp_thindraw_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask) +{ + pcb_coord_t w = mask ? pv->Mask : pv->Thickness; + pcb_coord_t r = w / 2; + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + if (mask) + pcb_gui->draw_arc(fg_gc, pv->X, pv->Y, r, r, 0, 360); + if (drawHole) { + r = pv->DrillingHole / 2; + pcb_gui->set_line_cap(bg_gc, Round_Cap); + pcb_gui->set_line_width(bg_gc, 0); + pcb_gui->draw_arc(bg_gc, pv->X, pv->Y, r, r, 0, 360); + } + return; + } + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pv)) { + if ((PCB_FLAG_SQUARE_GET(pv) == 0) || (PCB_FLAG_SQUARE_GET(pv) == 1)) { + pcb_coord_t l = pv->X - r; + pcb_coord_t b = pv->Y - r; + pcb_coord_t r = l + w; + pcb_coord_t t = b + w; + + pcb_gui->set_line_cap(fg_gc, Round_Cap); + pcb_gui->set_line_width(fg_gc, 0); + pcb_gui->draw_line(fg_gc, r, t, r, b); + pcb_gui->draw_line(fg_gc, l, t, l, b); + pcb_gui->draw_line(fg_gc, r, t, l, t); + pcb_gui->draw_line(fg_gc, r, b, l, b); + } + else + draw_square_pin_poly(fg_gc, pv->X, pv->Y, w, pcb_true, PCB_FLAG_SQUARE_GET(pv)); + + } + else if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pv)) { + draw_octagon_poly(fg_gc, pv->X, pv->Y, w, pcb_true); + } + else { /* draw a round pin or via */ + + pcb_gui->set_line_cap(fg_gc, Round_Cap); + pcb_gui->set_line_width(fg_gc, 0); + pcb_gui->draw_arc(fg_gc, pv->X, pv->Y, r, r, 0, 360); + } + + /* and the drilling hole (which is always round */ + if (drawHole) { + pcb_gui->set_line_cap(bg_gc, Round_Cap); + pcb_gui->set_line_width(bg_gc, 0); + pcb_gui->draw_arc(bg_gc, pv->X, pv->Y, pv->DrillingHole / 2, pv->DrillingHole / 2, 0, 360); + } +} + +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; + hid->fill_pcb_pad = pcb_dhlp_fill_pcb_pad; + hid->thindraw_pcb_pad = pcb_dhlp_thindraw_pcb_pad; + hid->fill_pcb_pv = pcb_dhlp_fill_pcb_pv; + hid->thindraw_pcb_pv = pcb_dhlp_thindraw_pcb_pv; +} Index: tags/1.2.7/src/hid_draw_helpers.h =================================================================== --- tags/1.2.7/src/hid_draw_helpers.h (nonexistent) +++ tags/1.2.7/src/hid_draw_helpers.h (revision 13657) @@ -0,0 +1,10 @@ +#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_fill_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask); +void pcb_dhlp_thindraw_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask); +void pcb_dhlp_fill_pcb_pv(pcb_hid_gc_t gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask); +void pcb_dhlp_thindraw_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pv, pcb_bool drawHole, pcb_bool mask); +void pcb_dhlp_draw_helpers_init(pcb_hid_t * hid); +#endif Index: tags/1.2.7/src/hid_extents.c =================================================================== --- tags/1.2.7/src/hid_extents.c (nonexistent) +++ tags/1.2.7/src/hid_extents.c (revision 13657) @@ -0,0 +1,165 @@ +#include "config.h" +#include "board.h" +#include "data.h" +#include "hid_draw_helpers.h" +#include "hid_extents.h" + +static pcb_box_t box; + +typedef struct hid_gc_s { + int width; +} hid_gc_s; + +static int extents_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_COPPER: + case PCB_LYT_OUTLINE: + case PCB_LYT_SILK: + case PCB_LYT_PDRILL: + case PCB_LYT_UDRILL: + return 1; + default: + return 0; + } + return 0; +} + +static pcb_hid_gc_t extents_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) malloc(sizeof(hid_gc_s)); + memset(rv, 0, sizeof(hid_gc_s)); + return rv; +} + +static void extents_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void extents_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t *screen) +{ +} + +static void extents_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ +} + +static void extents_set_color(pcb_hid_gc_t gc, const char *name) +{ +} + +static void extents_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ +} + +static void extents_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void extents_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ +} + +#define PEX(x,w) if (box.X1 > (x)-(w)) box.X1 = (x)-(w); \ + if (box.X2 < (x)+(w)) box.X2 = (x)+(w) +#define PEY(y,w) if (box.Y1 > (y)-(w)) box.Y1 = (y)-(w); \ + if (box.Y2 < (y)+(w)) box.Y2 = (y)+(w) + +static void extents_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + PEX(x1, gc->width); + PEY(y1, gc->width); + PEX(x2, gc->width); + PEY(y2, gc->width); +} + +static void extents_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) +{ + /* Naive but good enough. */ + PEX(cx, width + gc->width); + PEY(cy, height + gc->width); +} + +static void extents_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + PEX(x1, gc->width); + PEY(y1, gc->width); + PEX(x2, gc->width); + PEY(y2, gc->width); +} + +static void extents_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + PEX(cx, radius); + PEY(cy, radius); +} + +static void extents_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + int i; + for (i = 0; i < n_coords; i++) { + PEX(x[i], 0); + PEY(y[i], 0); + } +} + +static void extents_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + PEX(x1, 0); + PEY(y1, 0); + PEX(x2, 0); + PEY(y2, 0); +} + +static pcb_hid_t extents_hid; + +void hid_extents_init(void) +{ + static pcb_bool initialised = pcb_false; + + if (initialised) + return; + + memset(&extents_hid, 0, sizeof(pcb_hid_t)); + + pcb_dhlp_draw_helpers_init(&extents_hid); + + extents_hid.struct_size = sizeof(pcb_hid_t); + extents_hid.name = "extents-extents"; + extents_hid.description = "used to calculate extents"; + + extents_hid.set_layer_group = extents_set_layer_group; + extents_hid.make_gc = extents_make_gc; + extents_hid.destroy_gc = extents_destroy_gc; + extents_hid.set_drawing_mode = extents_set_drawing_mode; + extents_hid.render_burst = extents_render_burst; + extents_hid.set_color = extents_set_color; + extents_hid.set_line_cap = extents_set_line_cap; + extents_hid.set_line_width = extents_set_line_width; + extents_hid.set_draw_xor = extents_set_draw_xor; + extents_hid.draw_line = extents_draw_line; + extents_hid.draw_arc = extents_draw_arc; + extents_hid.draw_rect = extents_draw_rect; + extents_hid.fill_circle = extents_fill_circle; + extents_hid.fill_polygon = extents_fill_polygon; + extents_hid.fill_rect = extents_fill_rect; + + initialised = pcb_true; +} + +pcb_box_t *pcb_hid_get_extents_pinout(void *item) +{ + /* As this isn't a real "HID", we need to ensure we are initialised. */ + hid_extents_init(); + + box.X1 = COORD_MAX; + box.Y1 = COORD_MAX; + box.X2 = -COORD_MAX; + box.Y2 = -COORD_MAX; + + pcb_hid_expose_pinout(&extents_hid, item); + + return &box; +} Index: tags/1.2.7/src/hid_extents.h =================================================================== --- tags/1.2.7/src/hid_extents.h (nonexistent) +++ tags/1.2.7/src/hid_extents.h (revision 13657) @@ -0,0 +1,12 @@ +#ifndef PCB_HID_EXTENTS_H +#define PCB_HID_EXTENTS_H + +/* HID internal interfaces. These may ONLY be called from the HID + modules, not from the common PCB code. */ + +/* Convenience function that calls the expose callback for the item, + and returns the extents of what was drawn. */ +pcb_box_t *pcb_hid_get_extents_pinout(void *item); + + +#endif Index: tags/1.2.7/src/hid_flags.c =================================================================== --- tags/1.2.7/src/hid_flags.c (nonexistent) +++ tags/1.2.7/src/hid_flags.c (revision 13657) @@ -0,0 +1,98 @@ +#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 "hid_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; + const char *argv[2]; + if (cp != NULL) { + const pcb_hid_action_t *a; + 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_hid_find_action(buff); + 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] = buff; + argv[1] = NULL; + return pcb_hid_actionv_(a, len > 0, argv); + } + else { + /* slower but more generic way */ + return pcb_hid_parse_command(name); + } + } + else { + fprintf(stderr, "ERROR: pcb_hid_get_flag(%s) - not a path or an action\n", name); + } + } + 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]; +} Index: tags/1.2.7/src/hid_flags.h =================================================================== --- tags/1.2.7/src/hid_flags.h (nonexistent) +++ tags/1.2.7/src/hid_flags.h (revision 13657) @@ -0,0 +1,18 @@ +#ifndef PCB_HID_FLAGS_H +#define PCB_HID_FLAGS_H + +/* 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); + + +/* 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/1.2.7/src/hid_helper.c =================================================================== --- tags/1.2.7/src/hid_helper.c (nonexistent) +++ tags/1.2.7/src/hid_helper.c (revision 13657) @@ -0,0 +1,138 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "hid_helper.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "compat_misc.h" +#include "plug_io.h" + +char *pcb_layer_to_file_name(char *dest, pcb_layer_id_t lid, unsigned int flags, 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 (flags & PCB_LYT_OUTLINE) { + strcpy(dest, "outline"); + return dest; + } + + v = pcb_vlayer_get_first(flags); + 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; +} + + +void pcb_derive_default_filename(const char *pcbfile, pcb_hid_attribute_t * filename_attrib, const char *suffix, char **memory) +{ + char *buf; + char *pf; + + if (pcbfile == NULL) + pf = pcb_strdup("unknown.pcb"); + else + pf = pcb_strdup(pcbfile); + + if (!pf || (memory && filename_attrib->default_val.str_value != *memory)) + return; + + buf = (char *) malloc(strlen(pf) + strlen(suffix) + 1); + if (memory) + *memory = buf; + 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); + if (filename_attrib->default_val.str_value) + free((void *) filename_attrib->default_val.str_value); + filename_attrib->default_val.str_value = buf; + } + + free(pf); +} Index: tags/1.2.7/src/hid_helper.h =================================================================== --- tags/1.2.7/src/hid_helper.h (nonexistent) +++ tags/1.2.7/src/hid_helper.h (revision 13657) @@ -0,0 +1,25 @@ +#ifndef PCB_HID_HELPER_H +#define PCB_HID_HELPER_H + +/* maximum size of a derived suffix */ +#define PCB_DERIVE_FN_SUFF_LEN 20 + +typedef enum pcb_file_name_style_e { + /* 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, 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). + Returns dest. */ +void pcb_derive_default_filename(const char *pcbfile, pcb_hid_attribute_t * filename_attrib, const char *suffix, char **memory); + +#endif Index: tags/1.2.7/src/hid_init.c =================================================================== --- tags/1.2.7/src/hid_init.c (nonexistent) +++ tags/1.2.7/src/hid_init.c (revision 13657) @@ -0,0 +1,205 @@ +#include "config.h" + +#include "hid.h" +#include "hid_nogui.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 "hid_attrib.h" +#include "hid_init.h" +#include "misc_util.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "compat_inc.h" + +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; + pcb_hid_actions_init(); + + /* Setup a "nogui" default HID */ + pcb_gui = pcb_hid_nogui_get_hid(); + +#warning TODO: make this configurable - use pcb_conf_cmd_is_safe() to 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) */ + pcb_plugin_add_dir(pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S, "plugins", PCB_DIR_SEPARATOR_S, HOST, NULL)); + pcb_plugin_add_dir(pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S, "plugins", NULL)); + + /* 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_actions_uninit(); + 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; +} + +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; + } + + 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:; + for (i = 0; i < pcb_hid_num_hids; i++) + if (pcb_hid_list[i]->exporter) + fprintf(stderr, " %s", pcb_hid_list[i]->name); + fprintf(stderr, "\n"); + + return 0; +} + +pcb_hid_t **pcb_hid_enumerate() +{ + return pcb_hid_list; +} Index: tags/1.2.7/src/hid_init.h =================================================================== --- tags/1.2.7/src/hid_init.h (nonexistent) +++ tags/1.2.7/src/hid_init.h (revision 13657) @@ -0,0 +1,59 @@ +#ifndef PCB_HID_INIT_H +#define PCB_HID_INIT_H + +#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. */ +void 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; + + +#endif Index: tags/1.2.7/src/hid_nogui.c =================================================================== --- tags/1.2.7/src/hid_nogui.c (nonexistent) +++ tags/1.2.7/src/hid_nogui.c (revision 13657) @@ -0,0 +1,500 @@ +#include "config.h" + +#include +#include +#include + +#include "hid.h" +#include "compat_misc.h" +#include "compat_nls.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() + +typedef struct hid_gc_s { + int nothing_interesting_here; +} hid_gc_s; + +static pcb_hid_attribute_t *nogui_get_export_options(int *n_ret) +{ + CRASH("get_export_options"); + return 0; +} + +static void nogui_do_export(pcb_hid_attr_val_t * options) +{ + CRASH("do_export"); +} + +static void 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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) +{ +#warning TODO: make this crash after the set drawing mode transition +/* CRASH("set_drawing_mode");*/ +} + +static void nogui_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + /* the HID may decide to ingore this hook */ +} + +static void nogui_set_color(pcb_hid_gc_t gc, const char *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_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + CRASH("fill_pcb_pad"); +} + +static void nogui_thindraw_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + CRASH("thindraw_pcb_pad"); +} + +static void nogui_fill_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pad, pcb_bool drawHole, pcb_bool mask) +{ + CRASH("fill_pcb_pv"); +} + +static void nogui_thindraw_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t * pad, pcb_bool drawHole, pcb_bool mask) +{ + CRASH("thindraw_pcb_pv"); +} + +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) +{ + CRASH("get_coords"); +} + +static void nogui_set_crosshair(int x, int 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, void (*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"); +} + +static pcb_hidval_t nogui_add_block_hook(void (*func) (pcb_hidval_t data), pcb_hidval_t data) +{ + pcb_hidval_t rv; + CRASH("add_block_hook"); + rv.ptr = NULL; + return rv; +} + +static void nogui_stop_block_hook(pcb_hidval_t block_hook) +{ + CRASH("stop_block_hook"); +} + +static void nogui_log(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pcb_vfprintf(stdout, fmt, ap); + va_end(ap); +} + +static void nogui_logv(enum pcb_message_level level, const char *fmt, va_list ap) +{ + if ((conf_core.rc.quiet) && (level < PCB_MSG_ERROR)) + return; + if ((!conf_core.rc.verbose) && (level < PCB_MSG_INFO)) + return; + + switch (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; + } + pcb_vfprintf(stdout, fmt, ap); +} + +/* 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 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 NULL; + } + + /* 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 int nogui_confirm_dialog(const char *msg, ...) +{ + char *answer; + int ret = 0; + pcb_bool valid_answer = pcb_false; + va_list args; + + do { + va_start(args, msg); + pcb_vfprintf(stdout, msg, args); + va_end(args); + + printf(" ? 0=cancel 1 = ok : "); + + answer = read_stdin_line(); + + if ((answer == NULL) || (answer[0] == '1' && answer[1] == '\0')) { + ret = 1; + valid_answer = pcb_true; + } + else if (answer[0] == '0' && answer[1] == '\0') { + ret = 0; + valid_answer = pcb_true; + } + + free(answer); + } + while (!valid_answer); + return ret; +} + +static int nogui_close_confirm_dialog() +{ + return nogui_confirm_dialog(_("OK to lose data ?"), NULL); +} + +static void nogui_report_dialog(const char *title, const char *msg) +{ + printf("--- %s ---\n%s\n", title, msg); +} + +static char *nogui_prompt_for(const char *msg, const char *default_string) +{ + char *answer; + + if (default_string) + printf("%s [%s] : ", msg, default_string); + else + printf("%s : ", msg); + + answer = read_stdin_line(); + if (answer == NULL) + return pcb_strdup((default_string != NULL) ? default_string : ""); + else + return pcb_strdup(answer); +} + +/* 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 char *history_tag, int flags) +{ + char *answer; + + 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); +} + +static void *nogui_attr_dlg_new(pcb_hid_attribute_t *attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, const char *descr_, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev)) +{ + 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 int nogui_attribute_dialog(pcb_hid_attribute_t * attrs, int n_attrs, pcb_hid_attr_val_t * results, const char *title, const char *descr, void *caller_data) +{ + CRASH("attribute_dialog"); +} + +static void nogui_show_item(void *item) +{ + CRASH("show_item"); +} + +static void nogui_beep(void) +{ + putchar(7); + fflush(stdout); +} + +static int nogui_progress(int so_far, int total, const char *message) +{ + return 0; +} + +static pcb_hid_t *nogui_request_debug_draw(void) +{ + return NULL; +} + +static void nogui_flush_debug_draw(void) +{ +} + +static void nogui_finish_debug_draw(void) +{ +} + +static void nogui_create_menu(const char *menu, const char *action, const char *mnemonic, const char *accel, const char *tip, const char *cookie) +{ +} + +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_pcb_pad = nogui_fill_pcb_pad; + hid->thindraw_pcb_pad = nogui_thindraw_pcb_pad; + hid->fill_pcb_pv = nogui_fill_pcb_pv; + hid->thindraw_pcb_pv = nogui_thindraw_pcb_pv; + 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->add_block_hook = nogui_add_block_hook; + hid->stop_block_hook = nogui_stop_block_hook; + hid->log = nogui_log; + hid->logv = nogui_logv; + hid->confirm_dialog = nogui_confirm_dialog; + hid->close_confirm_dialog = nogui_close_confirm_dialog; + hid->report_dialog = nogui_report_dialog; + hid->prompt_for = nogui_prompt_for; + hid->fileselect = nogui_fileselect; + hid->attr_dlg_new = 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->attribute_dialog = nogui_attribute_dialog; + hid->show_item = nogui_show_item; + hid->beep = nogui_beep; + hid->progress = nogui_progress; + hid->request_debug_draw = nogui_request_debug_draw; + hid->flush_debug_draw = nogui_flush_debug_draw; + hid->finish_debug_draw = nogui_finish_debug_draw; + hid->create_menu = nogui_create_menu; +} + +static pcb_hid_t nogui_hid; + +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; +} Index: tags/1.2.7/src/hid_nogui.h =================================================================== --- tags/1.2.7/src/hid_nogui.h (nonexistent) +++ tags/1.2.7/src/hid_nogui.h (revision 13657) @@ -0,0 +1,7 @@ +#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); + +#endif Index: tags/1.2.7/src/ht_element.c =================================================================== --- tags/1.2.7/src/ht_element.c (nonexistent) +++ tags/1.2.7/src/ht_element.c (revision 13657) @@ -0,0 +1,9 @@ +#include +#include "config.h" +#include "obj_elem_list.h" + +#define HT(x) htep_ ## x +#include +#undef HT + + Index: tags/1.2.7/src/ht_element.h =================================================================== --- tags/1.2.7/src/ht_element.h (nonexistent) +++ tags/1.2.7/src/ht_element.h (revision 13657) @@ -0,0 +1,13 @@ +#ifndef PCB_HT_ELEMENT_H +#define PCB_HT_ELEMENT_H + +/* Hash: element -> pointer */ + +/* hash instance */ +typedef const pcb_element_t *htep_key_t; +typedef int htep_value_t; +#define HT(x) htep_ ## x +#include +#undef HT + +#endif Index: tags/1.2.7/src/ht_subc.c =================================================================== --- tags/1.2.7/src/ht_subc.c (nonexistent) +++ tags/1.2.7/src/ht_subc.c (revision 13657) @@ -0,0 +1,9 @@ +#include +#include "config.h" +#include "obj_subc_list.h" + +#define HT(x) htscp_ ## x +#include +#undef HT + + Index: tags/1.2.7/src/ht_subc.h =================================================================== --- tags/1.2.7/src/ht_subc.h (nonexistent) +++ tags/1.2.7/src/ht_subc.h (revision 13657) @@ -0,0 +1,13 @@ +#ifndef PCB_HT_SUBC_H +#define PCB_HT_SUBC_H + +/* Hash: subcircuit -> pointer */ + +/* hash instance */ +typedef const pcb_subc_t *htscp_key_t; +typedef int htscp_value_t; +#define HT(x) htscp_ ## x +#include +#undef HT + +#endif Index: tags/1.2.7/src/icons/Makefile.am =================================================================== --- tags/1.2.7/src/icons/Makefile.am (nonexistent) +++ tags/1.2.7/src/icons/Makefile.am (revision 13657) @@ -0,0 +1,4 @@ +## $Id$ + +EXTRA_DIST= hand.dat hcurs.dat lcurs.dat lock.dat + Index: tags/1.2.7/src/icons/hand.dat =================================================================== --- tags/1.2.7/src/icons/hand.dat (nonexistent) +++ tags/1.2.7/src/icons/hand.dat (revision 13657) @@ -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/1.2.7/src/icons/hcurs.dat =================================================================== --- tags/1.2.7/src/icons/hcurs.dat (nonexistent) +++ tags/1.2.7/src/icons/hcurs.dat (revision 13657) @@ -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/1.2.7/src/icons/lcurs.dat =================================================================== --- tags/1.2.7/src/icons/lcurs.dat (nonexistent) +++ tags/1.2.7/src/icons/lcurs.dat (revision 13657) @@ -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/1.2.7/src/icons/lock.dat =================================================================== --- tags/1.2.7/src/icons/lock.dat (nonexistent) +++ tags/1.2.7/src/icons/lock.dat (revision 13657) @@ -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/1.2.7/src/insert.c =================================================================== --- tags/1.2.7/src/insert.c (nonexistent) +++ tags/1.2.7/src/insert.c (revision 13657) @@ -0,0 +1,149 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* 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, + NULL, + NULL, + NULL, + 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.X - line->Point1.X) / (pcb_crosshair.Y - line->Point1.Y); + 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.X - line->Point1.X) / (pcb_crosshair.Y - line->Point1.Y); + 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/1.2.7/src/insert.h =================================================================== --- tags/1.2.7/src/insert.h (nonexistent) +++ tags/1.2.7/src/insert.h (revision 13657) @@ -0,0 +1,41 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Inserting points into objects */ + +#ifndef PCB_INSERT_H +#define PCB_INSERT_H + +#include "config.h" + +#define PCB_INSERT_TYPES (PCB_TYPE_POLY | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_RATLINE) + +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/1.2.7/src/intersect.c =================================================================== --- tags/1.2.7/src/intersect.c (nonexistent) +++ tags/1.2.7/src/intersect.c (revision 13657) @@ -0,0 +1,262 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* rectangle intersection/union routines. */ + +#include "config.h" + +#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/1.2.7/src/intersect.h =================================================================== --- tags/1.2.7/src/intersect.h (nonexistent) +++ tags/1.2.7/src/intersect.h (revision 13657) @@ -0,0 +1,42 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src/layer.c =================================================================== --- tags/1.2.7/src/layer.c (nonexistent) +++ tags/1.2.7/src/layer.c (revision 13657) @@ -0,0 +1,851 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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 "rtree.h" +#include "obj_pstk_inlines.h" + +pcb_virt_layer_t pcb_virt_layers[] = { + {"invisible", PCB_LYT_VIRTUAL + 1, PCB_LYT_VIRTUAL | PCB_LYT_INVIS }, + {"rats", PCB_LYT_VIRTUAL + 2, PCB_LYT_VIRTUAL | PCB_LYT_RAT }, + {"topassembly", PCB_LYT_VIRTUAL + 3, PCB_LYT_VIRTUAL | PCB_LYT_ASSY | PCB_LYT_TOP}, + {"bottomassembly", PCB_LYT_VIRTUAL + 4, PCB_LYT_VIRTUAL | PCB_LYT_ASSY | PCB_LYT_BOTTOM }, + {"fab", PCB_LYT_VIRTUAL + 5, PCB_LYT_VIRTUAL | PCB_LYT_FAB | PCB_LYT_LOGICAL }, + {"plated-drill", PCB_LYT_VIRTUAL + 6, PCB_LYT_VIRTUAL | PCB_LYT_PDRILL }, + {"unplated-drill", PCB_LYT_VIRTUAL + 7, PCB_LYT_VIRTUAL | PCB_LYT_UDRILL }, + {"csect", PCB_LYT_VIRTUAL + 8, PCB_LYT_VIRTUAL | PCB_LYT_CSECT | PCB_LYT_LOGICAL }, + {"dialog", PCB_LYT_VIRTUAL + 9, PCB_LYT_VIRTUAL | PCB_LYT_DIALOG | PCB_LYT_LOGICAL | PCB_LYT_NOEXPORT }, + { 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_OUTLINE, 2, "outline" }, + { PCB_LYT_RAT, 2, "rat" }, + { PCB_LYT_INVIS, 2, "invis" }, + { PCB_LYT_ASSY, 2, "assy" }, + { PCB_LYT_FAB, 2, "fab" }, + { PCB_LYT_PDRILL, 2, "plateddrill" }, + { PCB_LYT_UDRILL, 2, "unplateddrill" }, + { PCB_LYT_CSECT, 2, "cross-section" }, + { PCB_LYT_SUBSTRATE,2,"substrate" }, + { PCB_LYT_MISC, 2, "misc" }, + { 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) + +pcb_bool pcb_layer_is_pure_empty(pcb_layer_t *layer) +{ + /* normal case: a layer is empty if all lists are empty */ + 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); +} + +pcb_bool pcb_layer_is_empty_(pcb_board_t *pcb, pcb_layer_t *layer) +{ + pcb_layer_type_t flags; + + flags = pcb_layer_flags_(layer); + + if (flags == 0) + return 1; + + /* fast check: direct object */ + if (!pcb_layer_is_pure_empty(layer)) + return 0; + + if ((flags & PCB_LYT_COPPER) && (flags & PCB_LYT_TOP)) { /* if our layer is the top copper layer and we have an element pad on it, it's non-empty */ + PCB_PAD_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad)) + return 0; + } + PCB_ENDALL_LOOP; + } + + if ((flags & PCB_LYT_COPPER) && (flags & PCB_LYT_BOTTOM)) { /* if our layer is the bottom copper layer and we have an element pad on it, it's non-empty */ + PCB_PAD_ALL_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad)) + return 0; + } + PCB_ENDALL_LOOP; + } + + /* if any padstack has a shape on this layer, it is not empty */ + PCB_PADSTACK_LOOP(pcb->Data); + { + if (pcb_pstk_shape_at(pcb, padstack, layer) != NULL) + return 0; + } + PCB_END_LOOP; + +#warning TODO: check top silk and bottom silk for elements + + /* 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(pcb_data_t *Data, pcb_layer_t *Layer) +{ + if ((Layer >= pcb_uilayer.array) && (Layer < pcb_uilayer.array + vtlayer_len(&pcb_uilayer))) + return (Layer - pcb_uilayer.array) | PCB_LYT_UI; + + if (Layer->parent != 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(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_(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; + 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; +} + +#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 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) + return v; + return NULL; +} + + +int pcb_layer_list(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 < vtlayer_len(&pcb_uilayer); n++) + APPEND(n | PCB_LYT_UI | PCB_LYT_VIRTUAL); + + return used; +} + +int pcb_layer_list_any(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 < vtlayer_len(&pcb_uilayer); n++) + 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].type = 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].parent = pcb->Data; + 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)); +} + +#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; +} + +/* 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 = conf_core.appearance.color.layer[idx]; + lp->meta.real.selected_color = conf_core.appearance.color.layer_selected[idx]; + 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].type) & 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 = parent; +} + +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; + + /* 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_gui->confirm_dialog("You can't delete the last top-side layer\n", "Ok", NULL); + return 1; + } + + if (new_index == -1 && is_last_bottom_copper_layer(pcb, old_index)) { + pcb_gui->confirm_dialog("You can't delete the last bottom-side layer\n", "Ok", NULL); + return 1; + } + + pcb_undo_add_layer_move(old_index, new_index); + pcb_undo_inc_serial(); + + 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); + } + else if (new_index == -1) { /* Delete the layer at old_index */ + pcb_layergrp_id_t gid; + pcb_layergrp_t *g; + int grp_idx, remaining; + +#warning layer TODO remove objects, free fields layer_free(&pcb->Data->Layer[old_index]); + + /* 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; + } + + 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. */ + } + + 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) { + id &= ~(PCB_LYT_VIRTUAL | PCB_LYT_UI); + if ((id >= 0) && (id < vtlayer_len(&pcb_uilayer))) + return &(pcb_uilayer.array[id]); + } + return NULL; +} + +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(NULL, 0, 0); + if (src->arc_tree == NULL) src->arc_tree = pcb_r_create_tree(NULL, 0, 0); + if (src->text_tree == NULL) src->text_tree = pcb_r_create_tree(NULL, 0, 0); + if (src->polygon_tree == NULL) src->polygon_tree = pcb_r_create_tree(NULL, 0, 0); + + 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; + + assert(!src->is_bound); + + pcb = pcb_layer_get_top(src); + 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; + + 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); + } +} + +pcb_layer_t *pcb_layer_resolve_binding(pcb_board_t *pcb, pcb_layer_t *src) +{ + int l, score, best_score = 0; + pcb_layergrp_id_t gid; + 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); + } + else { + if (pcb_layergrp_list(pcb, src->meta.bound.type, &gid, 1) != 1) + return NULL; + } + + { + pcb_layergrp_t *grp = pcb->LayerGroups.grp+gid; + 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++; + + if (ly->name == src->name) /* mainly for NULL = NULL */ + score += 4; + + if ((ly->name != NULL) && (src->name != NULL)) { + if (strcmp(ly->name, src->name) == 0) + score += 4; + else if (pcb_strcasecmp(ly->name, src->name) == 0) + score += 2; + } + + if (score > best_score) { + best = ly; + best_score = score; + } + } + } + } + + return best; +} + +pcb_layer_t *pcb_layer_new_bound(pcb_data_t *data, pcb_layer_type_t type, const char *name) +{ + 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; + lay->parent = data; + + return lay; +} + +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; +} + +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_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; + +#warning layer TODO: 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, lid, v->type, is_empty); + } + + /* 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) +{ + /* if there's no GUI, that means no draw should be done */ + if (pcb_gui == NULL) + return 0; + + if (pcb_gui->set_layer_group != NULL) + return pcb_gui->set_layer_group(-1, pcb_layer_id(first->parent, first), PCB_LYT_VIRTUAL | PCB_LYT_UI, is_empty); + + /* 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->meta.real.Attributes)); + free(buf); +} + +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->type & loc) && (g->type & 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() +{ + static pcb_layer_id_t cache = -1; + pcb_layer_id_t id = pcb_layer_get_cached(PCB, &cache, PCB_LYT_BOTTOM, PCB_LYT_SILK); + assert(id >= 0); + return id; +} + +pcb_layer_id_t pcb_layer_get_top_silk() +{ + static pcb_layer_id_t cache = -1; + pcb_layer_id_t id = pcb_layer_get_cached(PCB, &cache, PCB_LYT_TOP, PCB_LYT_SILK); + assert(id >= 0); + return id; +} Index: tags/1.2.7/src/layer.h =================================================================== --- tags/1.2.7/src/layer.h (nonexistent) +++ tags/1.2.7/src/layer.h (revision 13657) @@ -0,0 +1,316 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_LAYER_H +#define PCB_LAYER_H + + +typedef long int pcb_layer_id_t; +typedef long int pcb_layergrp_id_t; + +/* 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 */ + 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_OUTLINE = 0x00001000, /* outline (contour of the board) */ + 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_ASSY = 0x00008000, /* (virtual) assembly drawing (top and bottom) */ + PCB_LYT_FAB = 0x00010000, /* (virtual) fab drawing (one, not in the stackup) */ + PCB_LYT_PDRILL = 0x00020000, /* (virtual) plated drills (affects all physical layers) */ + PCB_LYT_UDRILL = 0x00040000, /* (virtual) unplated drills (affects all physical layers) */ + PCB_LYT_UI = 0x00080000, /* (virtual) user interface drawings (feature plugins use this for displaying states or debug info) */ + PCB_LYT_CSECT = 0x00100000, /* (virtual) cross-section drawing (displaying layer groups) */ + PCB_LYT_SUBSTRATE= 0x00200000, /* substrate / insulator */ + PCB_LYT_MISC = 0x00400000, /* misc physical layers (e.g. adhesive) */ + PCB_LYT_DIALOG = 0x00800000, /* (virtual) dialog box drawings (e.g. font selector) - not to be interpreted in the board space */ + PCB_LYT_ANYTHING = 0x00FFFF00, /* MASK: layers consist anything */ + + /* misc properties */ + PCB_LYT_VIRTUAL = 0x01000000, /* the layer is not in the layer array (generated layer) */ + PCB_LYT_NOEXPORT = 0x02000000, /* should not show up in any of the exports */ + PCB_LYT_ANYPROP = 0x7F000000 /* 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, + PCB_VLY_DIALOG, + + /* 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 auto-generated (from pins, pads, elements) */ +} pcb_layer_combining_t; + + +#include "globalconst.h" +#include "global_typedefs.h" +#include "attrib.h" +#include "obj_all_list.h" + +struct pcb_layer_s { /* holds information about one layer */ + linelist_t Line; + textlist_t Text; + polylist_t Polygon; + arclist_t Arc; + pcb_data_t *parent; + + 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 */ + const char *color; /* color */ + const char *selected_color; + pcb_attribute_list_t Attributes; + 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 */ + } 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 */ + + 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(pcb_data_t *Data, 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; + +/* Returns whether an auto paste layer is empty - it may be nonempty + only because of element-side-effects */ +pcb_bool pcb_layer_is_paste_auto_empty(pcb_board_t *pcb, pcb_side_t side); + +/* Cached lookup of the first silk layer in the bottom or top group */ +pcb_layer_id_t pcb_layer_get_bottom_silk(); +pcb_layer_id_t pcb_layer_get_top_silk(); + +/* Return the board the layer is under */ +#define pcb_layer_get_top(layer) pcb_data_get_top((layer)->parent) + +/************ 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 SILKLAYER Layer[ \ + (conf_core.editor.show_solder_side ? pcb_layer_get_bottom_silk() : pcb_layer_get_top_silk())] +#define BACKSILKLAYER Layer[ \ + (conf_core.editor.show_solder_side ? pcb_layer_get_top_silk() : pcb_layer_get_bottom_silk())] + +#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 **************/ + +/* 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); +int pcb_layer_gui_set_g_ui(pcb_layer_t *first, int is_empty); + + +/* returns a bitfield of pcb_layer_type_t; returns 0 if layer_idx or layer is invalid. */ +unsigned int pcb_layer_flags(pcb_board_t *pcb, pcb_layer_id_t layer_idx); +unsigned int pcb_layer_flags_(pcb_layer_t *layer); + +/* 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); + +/* 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*. +*/ +int pcb_layer_list(pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len); +int pcb_layer_list_any(pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len); + +/**** layer creation (for load/import code) ****/ + +/* Reset layers to the bare minimum (double sided board) */ +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); + +/* Rename an existing layer by idx */ +int pcb_layer_rename(pcb_data_t *data, pcb_layer_id_t layer, const char *lname); + +/* changes the name of a layer; memory has to be already allocated */ +int pcb_layer_rename_(pcb_layer_t *Layer, char *Name); + + +/* 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); + +/* 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); + + +/* 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(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 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; +} 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); + +/* 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/1.2.7/src/layer_grp.c =================================================================== --- tags/1.2.7/src/layer_grp.c (nonexistent) +++ tags/1.2.7/src/layer_grp.c (revision 13657) @@ -0,0 +1,1021 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "layer_grp.h" +#include "compat_misc.h" +#include "event.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_gui->invalidate_all(); \ + } \ +} while(0) + +void pcb_layergrp_inhibit_inc(void) +{ + inhibit_notify++; +} + +void pcb_layergrp_inhibit_dec(void) +{ + inhibit_notify--; +} + +pcb_layergrp_id_t pcb_layergrp_id(pcb_board_t *pcb, 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 >= 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; +} + +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); + NOTIFY(pcb); + return gid; +} + +unsigned int pcb_layergrp_flags(pcb_board_t *pcb, pcb_layergrp_id_t gid) +{ + + if ((gid < 0) || (gid >= pcb->LayerGroups.len)) + return 0; + + return pcb->LayerGroups.grp[gid].type; +} + +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->type & PCB_LYT_MASK) + return pcb_false; + + if (g->type & PCB_LYT_PASTE) { + if (g->type & PCB_LYT_TOP) + return pcb_layer_is_paste_auto_empty(pcb, PCB_COMPONENT_SIDE); + if (g->type & PCB_LYT_BOTTOM) + return pcb_layer_is_paste_auto_empty(pcb, PCB_SOLDER_SIDE); + } + + /* copper layers are always non-empty if there are vias or pins because of the rings */ + if (g->type & PCB_LYT_COPPER) { + if ((pcb->Data->via_tree != NULL) && (pcb->Data->via_tree->size > 0)) + return pcb_false; + if ((pcb->Data->pin_tree != NULL) && (pcb->Data->pin_tree->size > 0)) + 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; +} + +static void pcb_layergrp_free_fields(pcb_layergrp_t *g) +{ + free(g->name); +} + + +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].type & loc) && (stack->grp[n].type & 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_(pcb_board_t *pcb, int omit_substrate) +{ + 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 */ + for(bl = stack->len; bl >= 0; bl--) { + if ((stack->grp[bl].type & PCB_LYT_BOTTOM) && (stack->grp[bl].type & 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); + + stack->len += room; + + stack->grp[bl].name = pcb_strdup("Intern"); + stack->grp[bl].type = PCB_LYT_INTERN | PCB_LYT_COPPER; + stack->grp[bl].valid = 1; + bl++; + if (!omit_substrate) { + stack->grp[bl].type = PCB_LYT_INTERN | PCB_LYT_SUBSTRATE; + stack->grp[bl].valid = 1; + } + return &stack->grp[bl-1]; + } + } + return NULL; +} + +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); + 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); + 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_OUTLINE); + if ((g != NULL) && (g[1].type & 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->type |= PCB_LYT_OUTLINE; + g->type &= ~PCB_LYT_COPPER; + free(g->name); + g->name = pcb_strdup("global outline"); +} + + +#define LAYER_IS_OUTLINE(idx) ((pcb->Data->Layer[idx].name != NULL) && ((strcmp(pcb->Data->Layer[idx].name, "route") == 0 || strcmp(pcb->Data->Layer[(idx)].name, "outline") == 0))) +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(LayerGroup); + + 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->type & PCB_LYT_INTERN) + pcb_layergrp_fix_turn_to_outline(g); + 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_glayer(pcb_board_t *pcb, pcb_layergrp_id_t grp, int is_empty) +{ + /* if there's no GUI, that means no draw should be done */ + if (pcb_gui == NULL) + return 0; + + if (pcb_gui->set_layer_group != NULL) + return pcb_gui->set_layer_group(grp, pcb->LayerGroups.grp[grp].lid[0], pcb_layergrp_flags(pcb, grp), is_empty); + + /* if the GUI doesn't have a set_layer, assume it wants to draw all layers */ + return 1; +} + +#define APPEND(n) \ + do { \ + if (res != NULL) { \ + if (used < res_len) { \ + res[used] = n; \ + used++; \ + } \ + } \ + else \ + used++; \ + } while(0) + +int pcb_layergrp_list(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_list_any(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) \ +do { \ + g = &(newg->grp[newg->len]); \ + g->valid = 1; \ + if (gname != NULL) \ + g->name = pcb_strdup(gname); \ + else \ + g->name = NULL; \ + g->type = flags; \ + newg->len++; \ +} while(0) + +void pcb_layer_group_setup_default(pcb_layer_stack_t *newg) +{ + pcb_layergrp_t *g; + + memset(newg, 0, sizeof(pcb_layer_stack_t)); + + NEWG(g, PCB_LYT_TOP | PCB_LYT_PASTE, "top_paste"); + NEWG(g, PCB_LYT_TOP | PCB_LYT_SILK, "top_silk"); + NEWG(g, PCB_LYT_TOP | PCB_LYT_MASK, "top_mask"); + NEWG(g, PCB_LYT_TOP | PCB_LYT_COPPER, "top_copper"); + NEWG(g, PCB_LYT_INTERN | PCB_LYT_SUBSTRATE, NULL); + + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_COPPER, "bottom_copper"); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_MASK, "bottom_mask"); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_SILK, "bottom_silk"); + NEWG(g, PCB_LYT_BOTTOM | PCB_LYT_PASTE, "bottom_paste"); + +/* NEWG(g, PCB_LYT_INTERN | PCB_LYT_OUTLINE, "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].type & 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)); +} + +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].type & 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].type & mask) == mask) { + steps--; + if (steps == 0) + return gid; + } + } + return -1; +} + +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].type & PCB_LYT_COPPER) && (pcb->LayerGroups.grp[n].type & 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_OUTLINE) { + pcb_layergrp_t *grp = pcb_get_grp_new_misc(pcb); + grp->type = PCB_LYT_OUTLINE | PCB_LYT_INTERN; + grp->name = pcb_strdup("outline"); + pcb_layer_create(pcb, pcb_layergrp_id(pcb, grp), ly->name); + 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:; + } + } + } + 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; +} + +void pcb_layergrp_upgrade_to_pstk(pcb_board_t *pcb) +{ + typedef struct lmap_s { + const char *name; + pcb_layer_type_t lyt; + pcb_layer_combining_t comb; + } lmap_t; + const lmap_t *m, lmap[] = { + {"top paste", PCB_LYT_TOP | PCB_LYT_PASTE, PCB_LYC_AUTO}, + {"top mask", PCB_LYT_TOP | PCB_LYT_MASK, PCB_LYC_SUB | PCB_LYC_AUTO}, + {"top silk", PCB_LYT_TOP | PCB_LYT_SILK, PCB_LYC_AUTO}, + {"top copper", PCB_LYT_TOP | PCB_LYT_COPPER, 0}, + {"any internal copper", PCB_LYT_INTERN | PCB_LYT_COPPER, 0}, + {"bottom copper", PCB_LYT_BOTTOM | PCB_LYT_COPPER, 0}, + {"bottom silk", PCB_LYT_BOTTOM | PCB_LYT_SILK, PCB_LYC_AUTO}, + {"bottom mask", PCB_LYT_BOTTOM | PCB_LYT_MASK, PCB_LYC_SUB | PCB_LYC_AUTO}, + {"bottom paste", PCB_LYT_BOTTOM | PCB_LYT_PASTE, PCB_LYC_AUTO}, + {NULL, 0} + }; + pcb_layergrp_t *grp; + pcb_layergrp_id_t gid; + + for(m = lmap; 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_misc(pcb); + gid = grp - pcb->LayerGroups.grp; + grp->type = m->lyt; + } + + grp->name = pcb_strdup(m->name); + if (grp->len == 0) { + pcb_layer_id_t lid = pcb_layer_create(pcb, gid, m->name); + if (lid >= 0) { + pcb->Data->Layer[lid].comb = m->comb; + } + } + } +} + + +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->type & loc) && (g->type & 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].type & PCB_LYT_COPPER) + st->cache.copper[st->cache.copper_len++] = n; + + st->cache.copper_valid = 1; +} + Index: tags/1.2.7/src/layer_grp.h =================================================================== --- tags/1.2.7/src/layer_grp.h (nonexistent) +++ tags/1.2.7/src/layer_grp.h (revision 13657) @@ -0,0 +1,219 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_LAYER_GRP_H +#define PCB_LAYER_GRP_H + +typedef struct pcb_layergrp_s pcb_layergrp_t; + +#include "layer.h" + +/* ---------------------------------------------------------------------- + * layer group. A layer group identifies layers which are always switched + * on/off together. + */ + +struct pcb_layergrp_s { + 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 type; + + 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(pcb_board_t *pcb, 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); + +/* call the gui to set a layer group */ +int pcb_layer_gui_set_glayer(pcb_board_t *pcb, pcb_layergrp_id_t grp, int is_empty); + +/* returns a bitfield of pcb_layer_type_t; returns 0 if layer_idx is invalid. */ +unsigned int pcb_layergrp_flags(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(pcb_board_t *pcb, pcb_layer_type_t mask, pcb_layergrp_id_t *res, int res_len); +int pcb_layergrp_list_any(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); + +/** 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); + +/* 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); + +/* 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); + +/********* 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_layer_stack_t *newg); /* 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); + +/* 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); + + + +/* 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); + +#endif Index: tags/1.2.7/src/layer_it.h =================================================================== --- tags/1.2.7/src/layer_it.h (nonexistent) +++ tags/1.2.7/src/layer_it.h (revision 13657) @@ -0,0 +1,120 @@ +/* + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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/1.2.7/src/layer_ui.c =================================================================== --- tags/1.2.7/src/layer_ui.c (nonexistent) +++ tags/1.2.7/src/layer_ui.c (revision 13657) @@ -0,0 +1,76 @@ +/* + * 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. + * + */ + +/* Virtual layers for UI and debug */ +#include "config.h" +#define GVT_DONT_UNDEF +#include "layer_ui.h" +#include "event.h" +#include + +vtlayer_t pcb_uilayer; + +pcb_layer_t *pcb_uilayer_alloc(const char *cookie, const char *name, const char *color) +{ + int n; + pcb_layer_t *l; + + if (cookie == NULL) + return NULL; + + for(n = 0; n < vtlayer_len(&pcb_uilayer); n++) { + l = &pcb_uilayer.array[n]; + if (l->meta.real.cookie == NULL) { + l->meta.real.cookie = cookie; + goto found; + } + } + + l = vtlayer_alloc_append(&pcb_uilayer, 1); +found:; + l->meta.real.cookie = cookie; + l->meta.real.color = color; + l->name = name; + l->meta.real.vis = 1; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + return l; +} + +void pcb_uilayer_free_all_cookie(const char *cookie) +{ + int n; + for(n = 0; n < vtlayer_len(&pcb_uilayer); n++) { + pcb_layer_t *l = &pcb_uilayer.array[n]; + if (l->meta.real.cookie == cookie) { +#warning TODO: free all objects + l->meta.real.cookie = NULL; + l->meta.real.color = l->name = NULL; + l->meta.real.vis = 0; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + } +} + Index: tags/1.2.7/src/layer_ui.h =================================================================== --- tags/1.2.7/src/layer_ui.h (nonexistent) +++ tags/1.2.7/src/layer_ui.h (revision 13657) @@ -0,0 +1,49 @@ +/* + * 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. + * + */ + +/* Virtual layers for UI and debug */ +#include "layer.h" + +/* layer vector: Elem=pcb_layer_t *; init=0 */ +#define GVT(x) vtlayer_ ## x +#define GVT_ELEM_TYPE pcb_layer_t +#define GVT_SIZE_TYPE size_t +#define GVT_DOUBLING_THRS 64 +#define GVT_START_SIZE 4 +#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 + +/* list of all UI layers */ +extern vtlayer_t pcb_uilayer; + +pcb_layer_t *pcb_uilayer_alloc(const char *cookie, const char *name, const char *color); +void pcb_uilayer_free_all_cookie(const char *cookie); + + Index: tags/1.2.7/src/layer_vis.c =================================================================== --- tags/1.2.7/src/layer_vis.c (nonexistent) +++ tags/1.2.7/src/layer_vis.c (revision 13657) @@ -0,0 +1,337 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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, PinOn, ViaOn, 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) { + if (On < 0) + On = !pcb_uilayer.array[Layer].meta.real.vis; + Layer &= ~(PCB_LYT_UI | PCB_LYT_VIRTUAL); + if (Layer >= vtlayer_len(&pcb_uilayer)) + return 0; + pcb_uilayer.array[Layer].meta.real.vis = On; + changed = 1; + goto done; + } + + if (On < 0) + On = !PCB->Data->Layer[Layer].meta.real.vis; + + if (conf_core.rc.verbose) + printf("pcb_layervis_change_group_vis(Layer=%ld, On=%d, ChangeStackOrder=%d)\n", Layer, On, ChangeStackOrder); + + /* 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->PinOn = pcb_true; + PCB->ViaOn = pcb_true; + PCB->SubcOn = pcb_true; + PCB->SubcPartsOn = pcb_true; + PCB->RatOn = pcb_true; + PCB->padstack_mark_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.PinOn = PCB->PinOn; + SavedStack.ViaOn = PCB->ViaOn; + 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->PinOn = SavedStack.PinOn; + PCB->ViaOn = SavedStack.ViaOn; + 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->type & PCB_LYT_MASK) || (g->type & 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]); + 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 */ +} + + +static void pcb_layer_confchg_color(conf_native_t *cfg, int arr_idx) +{ + if (PCB != NULL) { + pcb_layer_t *lp = pcb_get_layer(PCB->Data, arr_idx); + if (lp != NULL) { + lp->meta.real.color = conf_core.appearance.color.layer[arr_idx]; + lp->meta.real.selected_color = conf_core.appearance.color.layer_selected[arr_idx]; + } + } +} + +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"); + conf_native_t *n_c1 = conf_get_field("appearance/color/layer"); + conf_native_t *n_c2 = conf_get_field("appearance/color/layer_selected"); + static conf_hid_callbacks_t cbs_mask, cbs_c1, cbs_c2; + + 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); + } + + memset(&cbs_c1, 0, sizeof(conf_hid_callbacks_t)); + memset(&cbs_c2, 0, sizeof(conf_hid_callbacks_t)); + cbs_c1.val_change_post = pcb_layer_confchg_color; + cbs_c2.val_change_post = pcb_layer_confchg_color; + conf_hid_set_cb(n_c1, layer_vis_conf_id, &cbs_c1); + conf_hid_set_cb(n_c2, layer_vis_conf_id, &cbs_c2); + + + 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); +} Index: tags/1.2.7/src/layer_vis.h =================================================================== --- tags/1.2.7/src/layer_vis.h (nonexistent) +++ tags/1.2.7/src/layer_vis.h (revision 13657) @@ -0,0 +1,55 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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); + +/* (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/1.2.7/src/library.c =================================================================== --- tags/1.2.7/src/library.c (nonexistent) +++ tags/1.2.7/src/library.c (revision 13657) @@ -0,0 +1,144 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#warning cleanup TODO: replace this with genvect + +#include +#include +#include +#include "config.h" +#include "library.h" +#include "macro.h" +#include "compat_misc.h" + +#define STEP_LIBRARYMENU 10 +#define STEP_LIBRARYENTRY 20 + +/* --------------------------------------------------------------------------- + * get next slot for a library menu, allocates memory if necessary + */ +pcb_lib_menu_t *pcb_lib_menu_new(pcb_lib_t *lib, int *idx) +{ + pcb_lib_menu_t *menu = lib->Menu; + + /* realloc new memory if necessary and clear it */ + if (lib->MenuN >= lib->MenuMax) { + lib->MenuMax += STEP_LIBRARYMENU; + menu = (pcb_lib_menu_t *) realloc(menu, lib->MenuMax * sizeof(pcb_lib_menu_t)); + lib->Menu = menu; + memset(menu + lib->MenuN, 0, STEP_LIBRARYMENU * sizeof(pcb_lib_menu_t)); + } + if (idx != NULL) + *idx = lib->MenuN; + return (menu + lib->MenuN++); +} + +void pcb_lib_menu_free(pcb_lib_t *lib, int menuidx) +{ + pcb_lib_menu_t *menu = lib->Menu; + + if (menu[menuidx].Name != NULL) + free(menu[menuidx].Name); + if (menu[menuidx].directory != NULL) + free(menu[menuidx].directory); + + lib->MenuN--; + memmove(menu + menuidx, menu + menuidx + 1, sizeof(pcb_lib_menu_t) * (lib->MenuN - menuidx)); +} + +/* --------------------------------------------------------------------------- + * get next slot for a library entry, allocates memory if necessary + */ +pcb_lib_entry_t *pcb_lib_entry_new(pcb_lib_menu_t *Menu) +{ + pcb_lib_entry_t *entry = Menu->Entry; + + /* realloc new memory if necessary and clear it */ + if (Menu->EntryN >= Menu->EntryMax) { + Menu->EntryMax += STEP_LIBRARYENTRY; + entry = (pcb_lib_entry_t *) realloc(entry, Menu->EntryMax * sizeof(pcb_lib_entry_t)); + Menu->Entry = entry; + memset(entry + Menu->EntryN, 0, STEP_LIBRARYENTRY * sizeof(pcb_lib_entry_t)); + } + return (entry + Menu->EntryN++); +} + + +/* --------------------------------------------------------------------------- + * releases the memory that's allocated by the library + */ +void pcb_lib_free(pcb_lib_t *lib) +{ + PCB_MENU_LOOP(lib); + { + PCB_ENTRY_LOOP(menu); + { + if (!entry->ListEntry_dontfree) + free((char*)entry->ListEntry); + } + PCB_END_LOOP; + free(menu->Entry); + free(menu->Name); + free(menu->directory); + } + PCB_END_LOOP; + free(lib->Menu); + + /* clear struct */ + memset(lib, 0, sizeof(pcb_lib_t)); +} + +/* --------------------------------------------------------------------------- + * Add a new net to the netlist menu + */ +pcb_lib_menu_t *pcb_lib_net_new(pcb_lib_t *lib, char *name, const char *style) +{ + pcb_lib_menu_t *menu; + char temp[64]; + + sprintf(temp, " %s", name); + menu = pcb_lib_menu_new(lib, NULL); + menu->Name = pcb_strdup(temp); + menu->flag = 1; /* net is enabled by default */ + if (style == NULL || PCB_NSTRCMP("(unknown)", style) == 0) + menu->Style = NULL; + else + menu->Style = pcb_strdup(style); + return (menu); +} + +/* --------------------------------------------------------------------------- + * Add a connection to the net + */ +pcb_lib_entry_t *pcb_lib_conn_new(pcb_lib_menu_t *net, char *conn) +{ + pcb_lib_entry_t *entry = pcb_lib_entry_new(net); + + entry->ListEntry = pcb_strdup_null(conn); + entry->ListEntry_dontfree = 0; + + return (entry); +} Index: tags/1.2.7/src/library.h =================================================================== --- tags/1.2.7/src/library.h (nonexistent) +++ tags/1.2.7/src/library.h (revision 13657) @@ -0,0 +1,102 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_LIBRARY_H +#define PCB_LIBRARY_H + +#include "global_typedefs.h" + +typedef struct pcb_lib_entry_s pcb_lib_entry_t; +typedef struct pcb_lib_menu_s pcb_lib_menu_t; + +/* --------------------------------------------------------------------------- + * structure used by library routines + */ +struct pcb_lib_entry_s { + const char *ListEntry; /* the string for the selection box */ + int ListEntry_dontfree; /* do not free(ListEntry) if non-zero */ + /* This used to contain some char *AllocatedMemory, possibly with + * the intention of the following fields pointing into it. + * It was never used that way, so removing for now. + * TODO: re-introduce and actually use it for the following fields? + */ + const char *Package; /* package */ + const char *Value; /* the value field */ + const char *Description; /* some descriptive text */ +#if 0 + pcb_fp_type_t Type; + void **Tags; /* an array of void * tag IDs; last tag ID is NULL */ +#endif +}; + +/* If the internal flag is set, the only field that is valid is Name, + and the struct is allocated with malloc instead of + CreateLibraryEntry. These "internal" entries are used for + electrical paths that aren't yet assigned to a real net. */ + +struct pcb_lib_menu_s { + char *Name, /* name of the menu entry */ + *directory, /* Directory name library elements are from */ + *Style; /* routing style */ + pcb_cardinal_t EntryN, /* number of objects */ + EntryMax; /* number of reserved memory locations */ + pcb_lib_entry_t *Entry; /* the entries */ + char flag; /* used by the netlist window to enable/disable nets */ + char internal; /* if set, this is an internal-only entry, not + part of the global netlist. */ +}; + +typedef struct { + pcb_cardinal_t MenuN; /* number of objects */ + pcb_cardinal_t MenuMax; /* number of reserved memory locations */ + pcb_lib_menu_t *Menu; /* the entries */ +} pcb_lib_t; + +pcb_lib_menu_t *pcb_lib_menu_new(pcb_lib_t *, int *idx); +pcb_lib_entry_t *pcb_lib_entry_new(pcb_lib_menu_t *); +void pcb_lib_free(pcb_lib_t *); +void pcb_lib_menu_free(pcb_lib_t *lib, int menuidx); + +pcb_lib_menu_t *pcb_lib_net_new(pcb_lib_t *lib, char *name, const char *style); +pcb_lib_entry_t *pcb_lib_conn_new(pcb_lib_menu_t *net, char *conn); + + +#define PCB_MENU_LOOP(top) do { \ + pcb_cardinal_t l; \ + pcb_lib_menu_t *menu; \ + for (l = (top)->MenuN-1; l != -1; l--) \ + { \ + menu = &(top)->Menu[l] + +#define PCB_ENTRY_LOOP(top) do { \ + pcb_cardinal_t n; \ + pcb_lib_entry_t *entry; \ + for (n = (top)->EntryN-1; n != -1; n--) \ + { \ + entry = &(top)->Entry[n] + +#endif Index: tags/1.2.7/src/list_common.h =================================================================== --- tags/1.2.7/src/list_common.h (nonexistent) +++ tags/1.2.7/src/list_common.h (revision 13657) @@ -0,0 +1,35 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/list_conf.c =================================================================== --- tags/1.2.7/src/list_conf.c (nonexistent) +++ tags/1.2.7/src/list_conf.c (revision 13657) @@ -0,0 +1,26 @@ +/* + * 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. + * + */ + +#define FROM_CONF_C +#include "conf.h" +#include "list_conf.h" +#include Index: tags/1.2.7/src/list_conf.h =================================================================== --- tags/1.2.7/src/list_conf.h (nonexistent) +++ tags/1.2.7/src/list_conf.h (revision 13657) @@ -0,0 +1,49 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/macro.h =================================================================== --- tags/1.2.7/src/macro.h (nonexistent) +++ tags/1.2.7/src/macro.h (revision 13657) @@ -0,0 +1,81 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 + +/* --------------------------------------------------------------------------- + * macros to transform coord systems + * draw.c uses a different definition of TO_SCREEN + */ +#ifndef PCB_SWAP_IDENT +#define PCB_SWAP_IDENT conf_core.editor.show_solder_side +#endif + +#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))) +#define PCB_SQUARE(x) ((float) (x) * (float) (x)) + +/* --------------------------------------------------------------------------- + * returns the object ID + */ +#define PCB_OBJECT_ID(p) (((pcb_any_obj_t *) p)->ID) + +/* --------------------------------------------------------------------------- + * Determines if object is on front or back + */ +#define PCB_FRONT(o) \ + ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (o)) != 0) == PCB_SWAP_IDENT) + +/* --------------------------------------------------------------------------- + * Determines if an object is on the given side. side is either PCB_SOLDER_SIDE + * or PCB_COMPONENT_SIDE. + */ +#define PCB_ON_SIDE(element, side) \ + (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) == (side == PCB_SOLDER_SIDE)) + +/* --------------------------------------------------------------------------- + * some loop shortcuts + * + * 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/1.2.7/src/main.c =================================================================== --- tags/1.2.7/src/main.c (nonexistent) +++ tags/1.2.7/src/main.c (revision 13657) @@ -0,0 +1,606 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* 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 "flag_str.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "event.h" +#include "funchash.h" +#include "conf.h" +#include "conf_core.h" +#include +#include "layer_vis.h" +#include "obj_text.h" +#include "pcb_minuid.h" +#include "tool.h" + +#include "hid_actions.h" +#include "hid_init.h" +#include "compat_misc.h" +#include "compat_nls.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 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_strdup(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; + +void pcb_main_uninit(void) +{ + if (conf_isdirty(CFR_USER)) + conf_save_file(NULL, NULL, CFR_USER, 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 + * lib dmalloc. + */ + pcb_board_free(PCB); + free(PCB); + PCB = NULL; + + pcb_tool_uninit(); + pcb_hid_uninit(); + pcb_text_uninit(); + pcb_layer_vis_uninit(); + pcb_events_uninit(); + + pcb_strflg_uninit_buf(); + pcb_strflg_uninit_layerlist(); + + pcb_fp_uninit(); + pcb_fp_host_uninit(); + pcb_funchash_uninit(); + free(hid_argv_orig); + conf_uninit(); + pcb_io_uninit(); + pcb_plugin_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)); +} + +const char *pcb_action_args[] = { +/*short, -long, action, help */ + NULL, "-show-actions", "PrintActions()", "Print all available actions (human readable) and exit", + NULL, "-dump-actions", "DumpActions()", "Print all available actions (script readable) and exit", + NULL, "-dump-plugins", "DumpPlugins()", "Print all available plugins (script readable) and exit", + NULL, "-dump-plugindirs", "DumpPluginDirs()","Print directories plugins might be loaded from and exit", + NULL, "-show-paths", "PrintPaths()", "Print all configured paths and exit", + NULL, "-dump-config", "dumpconf(native,1)", "Print the config tree and exit", + "V", "-version", "PrintVersion()", "Print version info and exit", + NULL, "-copyright", "PrintCopyright()", "Print copyright and exit", + NULL, NULL, NULL /* terminator */ +}; + +void print_pup_err(pup_err_stack_t *entry, char *string) +{ + pcb_message(PCB_MSG_ERROR, "puplug: %s\n", string); +} + + +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; + char *command_line_pcb = NULL; + vtp0_t plugin_cli_conf; + +#ifdef LOCALEDIR + bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR); + textdomain(GETTEXT_PACKAGE); + bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); + setlocale(LC_ALL, ""); +#else + setlocale(LC_ALL, "C"); +#endif + + 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_minuid_init(); + conf_init(); + conf_core_init(); + conf_core_postproc(); /* to get all the paths initialized */ + 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 += 4) { + if (arg_match(cmd, cs[0], cs[1])) { + if (main_action == NULL) + main_action = cs[2]; + 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:; + } + conf_load_all(NULL, NULL); + + setbuf(stdout, 0); + InitPaths(argv[0]); + + pcb_fp_init(); + + + srand(time(NULL)); /* Set seed for rand() */ + + pcb_funchash_init(); + pcb_units_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_events_init(); + pcb_text_init(); + pcb_tool_init(); + + pup_init(&pcb_pup); + pcb_pup.error_stack_enable = 1; + pup_buildin_load(&pcb_pup, pup_buildins); + pup_autoload_dir(&pcb_pup, NULL, NULL); + 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); + } + + pcb_hid_init(); + 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: { + conf_listitem_t *i; + int n; + const char *g; + + pcb_gui = NULL; + conf_loop_list_str(&conf_core.rc.preferred_gui, i, g, n) { + 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) { + pcb_hid_parse_command(main_action); + exit(0); + } + + pcb_gui->parse_arguments(&hid_argc, &hid_argv); + + /* 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"); + 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_crosshair_set_mode(PCB_MODE_ARROW); + + if (command_line_pcb) { + /* keep filename even if initial load command failed; + * file might not exist + */ + if (pcb_load_pcb(command_line_pcb, NULL, pcb_true, 0)) + 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_hid_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_hid_parse_actions(conf_core.rc.action_string); + } + + if (pcb_gui->printer || pcb_gui->exporter) { + /* Workaround to fix batch output for non-C locales */ + setlocale(LC_NUMERIC, "C"); + if (pcb_data_is_empty(PCB->Data)) { + pcb_message(PCB_MSG_ERROR, "Can't export empty board - the board needs to contain at least one object.\n"); + exit(1); + } + else + pcb_gui->do_export(0); + 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_crosshair_set_mode(PCB_MODE_ARROW); + pcb_event(PCB_EVENT_LIBRARY_CHANGED, NULL); + } + } while(pcb_gui != NULL); + + pcb_main_uninit(); + + return (0); +} Index: tags/1.2.7/src/main_act.c =================================================================== --- tags/1.2.7/src/main_act.c (nonexistent) +++ tags/1.2.7/src/main_act.c (revision 13657) @@ -0,0 +1,313 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#define Progname "pcb-rnd" + +#include "config.h" + +#include "hid_actions.h" +#include "hid_init.h" +#include "conf_core.h" +#include "plugins.h" + + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_PrintActions[] = "PrintActions()"; + +static const char pcb_acth_PrintActions[] = "Print all actions available."; + +int pcb_act_PrintActions(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_print_actions(); + return 0; +} +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_DumpActions[] = "DumpActions()"; + +static const char pcb_acth_DumpActions[] = "Dump all actions available."; + +int pcb_act_DumpActions(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_dump_actions(); + 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[]; +static int help_main(void) { + const char **cs; + for(cs = pcb_action_args; cs[2] != NULL; cs += 4) { + 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; +} + +int pcb_act_PrintUsage(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + u(""); + if (argc > 0) { + pcb_hid_t **hl = pcb_hid_enumerate(); + int i; + + if (strcmp(argv[0], "invocation") == 0) return help_invoc(); + if (strcmp(argv[0], "main") == 0) return help_main(); + + for (i = 0; hl[i]; i++) { + if ((hl[i]->usage != NULL) && (strcmp(argv[0], hl[i]->name) == 0)) { + if (argc > 1) + return hl[i]->usage(argv[1]); + else + return hl[i]->usage(NULL); + } + } + fprintf(stderr, "No help available for %s\n", argv[0]); + return -1; + } + else + help0(); + return 0; +} + + +/* --------------------------------------------------------------------------- */ +static const char pcb_acts_PrintVersion[] = "PrintVersion()"; + +static const char pcb_acth_PrintVersion[] = "Print version."; + +int pcb_act_PrintVersion(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + printf("pcb-rnd version %s\n", PCB_VERSION); + return 0; +} + +/* --------------------------------------------------------------------------- */ +static const char pcb_acts_PrintCopyright[] = "PrintCopyright()"; + +static const char pcb_acth_PrintCopyright[] = "Print copyright notice."; + +int pcb_act_PrintCopyright(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + printf("\n" + " COPYRIGHT for the original pcb program:\n\n" + " PCB, interactive printed circuit board design\n" + " Copyright (C) 1994,1995,1996,1997 Thomas Nau\n" + " Copyright (C) 1998, 1999, 2000 Harry Eaton\n\n"); + printf(" COPYRIGHT for %s (pcb-rnd) version %s:\n" + " pcb-rnd, a fork of PCB with random improvements\n" + " Copyright (C) 2013, 2014, 2015, 2016, 2017 Tibor 'Igor2' Palinkas\n\n", Progname, PCB_VERSION); + 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"); + 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"); +} + +int pcb_act_PrintPaths(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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); + return 0; +} + +/* --------------------------------------------------------------------------- */ +static const char pcb_acts_DumpPlugins[] = "DumpPlugins()"; + +static const char pcb_acth_DumpPlugins[] = "Print plugins loaded in a format digestable by scripts."; + +int pcb_act_DumpPlugins(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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); + + return 0; +} + + +static const char pcb_acts_DumpPluginDirs[] = "DumpPluginDirs()"; + +static const char pcb_acth_DumpPluginDirs[] = "Print plugins directories in a format digestable by scripts."; + +int pcb_act_DumpPluginDirs(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + char **p; + for(p = pcb_pup_paths; *p != NULL; p++) + printf("%s\n", *p); + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_hid_action_t main_action_list[] = { + {"PrintActions", 0, pcb_act_PrintActions, + pcb_acth_PrintActions, pcb_acts_PrintActions} + , + {"DumpActions", 0, pcb_act_DumpActions, + pcb_acth_DumpActions, pcb_acts_DumpActions} + , + {"PrintUsage", 0, pcb_act_PrintUsage, + pcb_acth_PrintUsage, pcb_acts_PrintUsage} + , + {"PrintVersion", 0, pcb_act_PrintVersion, + pcb_acth_PrintVersion, pcb_acts_PrintVersion} + , + {"PrintCopyright", 0, pcb_act_PrintCopyright, + pcb_acth_PrintCopyright, pcb_acts_PrintCopyright} + , + {"PrintPaths", 0, pcb_act_PrintPaths, + pcb_acth_PrintPaths, pcb_acts_PrintPaths} + , + {"DumpPlugins", 0, pcb_act_DumpPlugins, + pcb_acth_DumpPlugins, pcb_acts_DumpPlugins} + , + {"DumpPluginDirs", 0, pcb_act_DumpPluginDirs, + pcb_acth_DumpPluginDirs, pcb_acts_DumpPluginDirs} +}; + +PCB_REGISTER_ACTIONS(main_action_list, NULL) Index: tags/1.2.7/src/math_helper.h =================================================================== --- tags/1.2.7/src/math_helper.h (nonexistent) +++ tags/1.2.7/src/math_helper.h (revision 13657) @@ -0,0 +1,67 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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)) + +/* --------------------------------------------------------------------------- + * 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/1.2.7/src/misc_util.c =================================================================== --- tags/1.2.7/src/misc_util.c (nonexistent) +++ tags/1.2.7/src/misc_util.c (revision 13657) @@ -0,0 +1,194 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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); +} + +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); +} Index: tags/1.2.7/src/misc_util.h =================================================================== --- tags/1.2.7/src/misc_util.h (nonexistent) +++ tags/1.2.7/src/misc_util.h (revision 13657) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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); + +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); + +#endif Index: tags/1.2.7/src/move.c =================================================================== --- tags/1.2.7/src/move.c (nonexistent) +++ tags/1.2.7/src/move.c (revision 13657) @@ -0,0 +1,269 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* functions used to move pins, elements ... + */ + +#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 "hid_actions.h" +#include "compat_misc.h" +#include "obj_all_op.h" +#include "obj_pstk_op.h" + +pcb_opfunc_t MoveFunctions = { + pcb_lineop_move, + pcb_textop_move, + pcb_polyop_move, + pcb_viaop_move, + pcb_elemop_move, + pcb_elemop_move_name, + NULL, + NULL, + 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, + pcb_viaop_move_noclip, + NULL, + NULL, + NULL, + NULL, + 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, + pcb_viaop_clip, + NULL, + NULL, + NULL, + NULL, + 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, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arcop_move_to_layer, + pcb_ratop_move_to_layer, + NULL, + NULL, /* subc */ + NULL /* padstack */ +}; + +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_TYPE_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_TYPE_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_TYPE_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_TYPE_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_TYPE_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_TYPE_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_TYPEMASK_ALL); + /* passing pcb_true to above operation causes Undoserial to auto-increment */ + return (changed); +} Index: tags/1.2.7/src/move.h =================================================================== --- tags/1.2.7/src/move.h (nonexistent) +++ tags/1.2.7/src/move.h (revision 13657) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_MOVE_H +#define PCB_MOVE_H + +#include "config.h" + +/*** Transformation macros and constants ***/ +#define PCB_MOVE(xs,ys,deltax,deltay) \ + { \ + ((xs) += (deltax)); \ + ((ys) += (deltay)); \ + } + +#define PCB_MOVE_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PSTK | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_ELEMENT_NAME | \ + PCB_TYPE_POLY | PCB_TYPE_POLY_POINT | PCB_TYPE_LINE_POINT | PCB_TYPE_ARC | PCB_TYPE_ARC_POINT) +#define PCB_MOVETOLAYER_TYPES \ + (PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_POLY | PCB_TYPE_RATLINE | PCB_TYPE_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); + +#endif Index: tags/1.2.7/src/netlist.c =================================================================== --- tags/1.2.7/src/netlist.c (nonexistent) +++ tags/1.2.7/src/netlist.c (revision 13657) @@ -0,0 +1,322 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* generic netlist operations + */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "error.h" +#include "plug_io.h" +#include "find.h" +#include "rats.h" +#include "hid_actions.h" +#include "compat_misc.h" +#include "netlist.h" +#include "event.h" + +#define STEP_POINT 100 + +/* + int PCB->NetlistLib[n].MenuN + char * PCB->NetlistLib[n].Menu[i].Name + [0] == '*' (ok for rats) or ' ' (skip for rats) + [1] == unused + [2..] actual name + char * PCB->NetlistLib[n].Menu[i].Style + int PCB->NetlistLib[n].Menu[i].EntryN + char * PCB->NetlistLib[n].Menu[i].Entry[j].ListEntry +*/ + +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); + } +} + +pcb_lib_menu_t *pcb_netnode_to_netname(const char *nodename) +{ + int i, j; + /*printf("nodename [%s]\n", nodename); */ + for (i = 0; i < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; i++) { + for (j = 0; j < PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i].EntryN; j++) { + if (strcmp(PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i].Entry[j].ListEntry, nodename) == 0) { + /*printf(" in [%s]\n", PCB->NetlistLib.Menu[i].Name); */ + return &(PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i]); + } + } + } + return 0; +} + +pcb_lib_menu_t *pcb_netname_to_netname(const char *netname) +{ + int i; + + if ((netname[0] == '*' || netname[0] == ' ') && netname[1] == ' ') { + /* Looks like we were passed an internal netname, skip the prefix */ + netname += 2; + } + for (i = 0; i < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; i++) { + if (strcmp(PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i].Name + 2, netname) == 0) { + return &(PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i]); + } + } + return 0; +} + +int pcb_pin_name_to_xy(pcb_lib_entry_t * pin, pcb_coord_t *x, pcb_coord_t *y) +{ + pcb_connection_t conn; + if (!pcb_rat_seek_pad(pin, &conn, pcb_false)) + return 1; + pcb_obj_center(conn.obj, x, y); + return 0; +} + +void pcb_netlist_find(pcb_lib_menu_t * net, pcb_lib_entry_t * pin) +{ + pcb_coord_t x, y; + if (pcb_pin_name_to_xy(net->Entry, &x, &y)) + return; + pcb_lookup_conn(x, y, 1, 1, PCB_FLAG_FOUND); +} + +void pcb_netlist_select(pcb_lib_menu_t * net, pcb_lib_entry_t * pin) +{ + pcb_coord_t x, y; + if (pcb_pin_name_to_xy(net->Entry, &x, &y)) + return; + pcb_lookup_conn(x, y, 1, 1, PCB_FLAG_SELECTED); +} + +void pcb_netlist_rats(pcb_lib_menu_t * net, pcb_lib_entry_t * pin) +{ + net->Name[0] = ' '; + net->flag = 1; + pcb_netlist_changed(0); +} + +void pcb_netlist_norats(pcb_lib_menu_t * net, pcb_lib_entry_t * pin) +{ + net->Name[0] = '*'; + net->flag = 0; + 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. */ +void pcb_netlist_clear(pcb_lib_menu_t * net, pcb_lib_entry_t * pin) +{ + pcb_lib_t *netlist = (pcb_lib_t *) & PCB->NetlistLib; + int ni, pi; + + if (net == 0) { + /* Clear the entire netlist. */ + for (ni = 0; ni < PCB_NUM_NETLISTS; ni++) + pcb_lib_free(&(PCB->NetlistLib[ni])); + } + else if (pin == 0) { + /* Remove a net from the netlist. */ + ni = net - netlist->Menu; + if (ni >= 0 && ni < netlist->MenuN) { + /* if there is exactly one item, MenuN is 1 and ni is 0 */ + if (netlist->MenuN - ni > 1) + memmove(net, net + 1, (netlist->MenuN - ni - 1) * sizeof(*net)); + netlist->MenuN--; + } + } + else { + /* Remove a pin from the given net. Note that this may leave an + empty net, which is different than removing the net + (above). */ + pi = pin - net->Entry; + if (pi >= 0 && pi < net->EntryN) { + /* if there is exactly one item, MenuN is 1 and ni is 0 */ + if (net->EntryN - pi > 1) + memmove(pin, pin + 1, (net->EntryN - pi - 1) * sizeof(*pin)); + net->EntryN--; + } + } + pcb_netlist_changed(0); +} + +void pcb_netlist_style(pcb_lib_menu_t * net, const char *style) +{ + free(net->Style); + net->Style = pcb_strdup_null((char *) style); +} + +pcb_lib_menu_t *pcb_netlist_find_net4pinname(pcb_board_t *pcb, const char *pin) +{ + int n; + + for (n = 0; n < pcb->NetlistLib[PCB_NETLIST_EDITED].MenuN; n++) { + pcb_lib_menu_t *menu = &pcb->NetlistLib[PCB_NETLIST_EDITED].Menu[n]; + int p; + for (p = 0; p < menu->EntryN; p++) { + pcb_lib_entry_t *entry = &menu->Entry[p]; + if (strcmp(entry->ListEntry, pin) == 0) + return menu; + } + } + return NULL; +} + +static pcb_lib_menu_t *pcb_netlist_find_net4pin_any(pcb_board_t *pcb, const char *ename, const char *pname) +{ + char pinname[256]; + int len; + + if ((ename == NULL) || (pname == NULL)) + return NULL; + + len = pcb_snprintf(pinname, sizeof(pinname), "%s-%s", ename, pname); + if (len >= sizeof(pinname)) + return NULL; + + return pcb_netlist_find_net4pinname(pcb, pinname); +} + +pcb_lib_menu_t *pcb_netlist_find_net4pin(pcb_board_t *pcb, const pcb_pin_t *pin) +{ + const pcb_element_t *e = pin->Element; + + if (e == NULL) + return NULL; + + return pcb_netlist_find_net4pin_any(pcb, e->Name[PCB_ELEMNAME_IDX_REFDES].TextString, pin->Number); +} + + +pcb_lib_menu_t *pcb_netlist_find_net4pad(pcb_board_t *pcb, const pcb_pad_t *pad) +{ + const pcb_element_t *e = pad->Element; + + if (e == NULL) + return NULL; + + return pcb_netlist_find_net4pin_any(pcb, e->Name[PCB_ELEMNAME_IDX_REFDES].TextString, pad->Number); +} + +pcb_cardinal_t pcb_netlist_net_idx(pcb_board_t *pcb, pcb_lib_menu_t *net) +{ + pcb_lib_menu_t *first = &pcb->NetlistLib[PCB_NETLIST_EDITED].Menu[0]; + pcb_lib_menu_t *last = &pcb->NetlistLib[PCB_NETLIST_EDITED].Menu[pcb->NetlistLib[PCB_NETLIST_EDITED].MenuN-1]; + + if ((net < first) || (net > last)) + return PCB_NETLIST_INVALID_INDEX; + + return net - first; +} + +/* --------------------------------------------------------------------------- + * get next slot for a subnet, allocates memory if necessary + */ +pcb_net_t *pcb_net_new(pcb_netlist_t *Netlist) +{ + pcb_net_t *net = Netlist->Net; + + /* realloc new memory if necessary and clear it */ + if (Netlist->NetN >= Netlist->NetMax) { + Netlist->NetMax += STEP_POINT; + net = (pcb_net_t *) realloc(net, Netlist->NetMax * sizeof(pcb_net_t)); + Netlist->Net = net; + memset(net + Netlist->NetN, 0, STEP_POINT * sizeof(pcb_net_t)); + } + return (net + Netlist->NetN++); +} + +/* --------------------------------------------------------------------------- + * get next slot for a net list, allocates memory if necessary + */ +pcb_netlist_t *pcb_netlist_new(pcb_netlist_list_t *Netlistlist) +{ + pcb_netlist_t *netlist = Netlistlist->NetList; + + /* realloc new memory if necessary and clear it */ + if (Netlistlist->NetListN >= Netlistlist->NetListMax) { + Netlistlist->NetListMax += STEP_POINT; + netlist = (pcb_netlist_t *) realloc(netlist, Netlistlist->NetListMax * sizeof(pcb_netlist_t)); + Netlistlist->NetList = netlist; + memset(netlist + Netlistlist->NetListN, 0, STEP_POINT * sizeof(pcb_netlist_t)); + } + return (netlist + Netlistlist->NetListN++); +} + +/* --------------------------------------------------------------------------- + * frees memory used by a net + */ +void pcb_netlist_free(pcb_netlist_t *Netlist) +{ + if (Netlist) { + PCB_NET_LOOP(Netlist); + { + pcb_net_free(net); + } + PCB_END_LOOP; + free(Netlist->Net); + memset(Netlist, 0, sizeof(pcb_netlist_t)); + } +} + +/* --------------------------------------------------------------------------- + * frees memory used by a net list + */ +void pcb_netlist_list_free(pcb_netlist_list_t *Netlistlist) +{ + if (Netlistlist) { + PCB_NETLIST_LOOP(Netlistlist); + { + pcb_netlist_free(netlist); + } + PCB_END_LOOP; + free(Netlistlist->NetList); + memset(Netlistlist, 0, sizeof(pcb_netlist_list_t)); + } +} + +/* --------------------------------------------------------------------------- + * frees memory used by a subnet + */ +void pcb_net_free(pcb_net_t *Net) +{ + if (Net) { + free(Net->Connection); + memset(Net, 0, sizeof(pcb_net_t)); + } +} Index: tags/1.2.7/src/netlist.h =================================================================== --- tags/1.2.7/src/netlist.h (nonexistent) +++ tags/1.2.7/src/netlist.h (revision 13657) @@ -0,0 +1,111 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_NETLIST_H +#define PCB_NETLIST_H + +/* generic netlist operations */ +#include "config.h" +#include "library.h" +#include "route_style.h" + +struct pcb_net_s { /* holds a net of connections */ + pcb_cardinal_t ConnectionN, /* the number of connections contained */ + ConnectionMax; /* max connections from malloc */ + pcb_connection_t *Connection; + pcb_route_style_t *Style; +}; + +typedef struct { /* holds a list of nets */ + pcb_cardinal_t NetN, /* the number of subnets contained */ + NetMax; /* max subnets from malloc */ + pcb_net_t *Net; +} pcb_netlist_t; + +typedef struct { /* holds a list of net lists */ + pcb_cardinal_t NetListN, /* the number of net lists contained */ + NetListMax; /* max net lists from malloc */ + pcb_netlist_t *NetList; +} pcb_netlist_list_t; + + +void pcb_netlist_changed(int force_unfreeze); +pcb_lib_menu_t *pcb_netnode_to_netname(const char *nodename); +pcb_lib_menu_t *pcb_netname_to_netname(const char *netname); + +int pcb_pin_name_to_xy(pcb_lib_entry_t *pin, pcb_coord_t *x, pcb_coord_t *y); +void pcb_netlist_find(pcb_lib_menu_t *net, pcb_lib_entry_t *pin); +void pcb_netlist_select(pcb_lib_menu_t *net, pcb_lib_entry_t *pin); +void pcb_netlist_rats(pcb_lib_menu_t *net, pcb_lib_entry_t *pin); +void pcb_netlist_norats(pcb_lib_menu_t *net, pcb_lib_entry_t *pin); +void pcb_netlist_clear(pcb_lib_menu_t *net, pcb_lib_entry_t *pin); +void pcb_netlist_style(pcb_lib_menu_t *net, const char *style); + +/* Return the net entry for a pin name (slow search). The pin name is + like "U101-5", so element's refdes, dash, pin number */ +pcb_lib_menu_t *pcb_netlist_find_net4pinname(pcb_board_t *pcb, const char *pinname); + +/* Same as pcb_netlist_find_net4pinname but with pin pointer */ +pcb_lib_menu_t *pcb_netlist_find_net4pin(pcb_board_t *pcb, const pcb_pin_t *pin); +pcb_lib_menu_t *pcb_netlist_find_net4pad(pcb_board_t *pcb, const pcb_pad_t *pad); + + +/* Evaluate to const char * name of the network; lmt is (pcb_lib_menu_t *) */ +#define pcb_netlist_name(lmt) ((const char *)((lmt)->Name+2)) + +/* Evaluate to 0 or 1 depending on whether the net is marked with *; lmt is (pcb_lib_menu_t *) */ +#define pcb_netlist_is_bad(lmt) (((lmt)->Name[0]) == '*') + + +/* Return the index of the net or PCB_NETLIST_INVALID_INDEX if the net is not + on the netlist. NOTE: indices returned are valid only until the first + netlist change! */ +pcb_cardinal_t pcb_netlist_net_idx(pcb_board_t *pcb, pcb_lib_menu_t *net); + +#define PCB_NETLIST_INVALID_INDEX ((pcb_cardinal_t)(-1)) + +pcb_net_t *pcb_net_new(pcb_netlist_t *); +pcb_netlist_t *pcb_netlist_new(pcb_netlist_list_t *); +void pcb_netlist_list_free(pcb_netlist_list_t *); +void pcb_netlist_free(pcb_netlist_t *); +void pcb_net_free(pcb_net_t *); + +#define PCB_NETLIST_LOOP(top) do { \ + pcb_cardinal_t n; \ + pcb_netlist_t * netlist; \ + for (n = (top)->NetListN-1; n != -1; n--) \ + { \ + netlist = &(top)->NetList[n] + +#define PCB_NET_LOOP(top) do { \ + pcb_cardinal_t n; \ + pcb_net_t * net; \ + for (n = (top)->NetN-1; n != -1; n--) \ + { \ + net = &(top)->Net[n] + + +#endif Index: tags/1.2.7/src/netlist_act.c =================================================================== --- tags/1.2.7/src/netlist_act.c (nonexistent) +++ tags/1.2.7/src/netlist_act.c (revision 13657) @@ -0,0 +1,374 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* generic netlist operations + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "action_helper.h" +#include "data.h" +#include "board.h" +#include "error.h" +#include "plug_io.h" +#include "hid_actions.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "netlist.h" + +static int pcb_netlist_swap() +{ + char *pins[3] = { NULL, NULL, NULL }; + int next = 0, n; + int ret = -1; + pcb_lib_menu_t *nets[2]; + + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin)) { + int le, lp; + + if (next > 2) { + pcb_message(PCB_MSG_ERROR, "Exactly two pins should be selected for swap (more than 2 selected at the moment)\n"); + goto quit; + } + + le = strlen(element->Name[1].TextString); + lp = strlen(pin->Number); + pins[next] = malloc(le + lp + 2); + sprintf(pins[next], "%s-%s", element->Name[1].TextString, pin->Number); + next++; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + if (next < 2) { + pcb_message(PCB_MSG_ERROR, "Exactly two pins should be selected for swap (less than 2 selected at the moment)\n"); + goto quit; + } + + + nets[0] = pcb_netlist_find_net4pinname(PCB, pins[0]); + nets[1] = pcb_netlist_find_net4pinname(PCB, pins[1]); + if ((nets[0] == NULL) || (nets[1] == NULL)) { + pcb_message(PCB_MSG_ERROR, "That pin is not on a net.\n"); + goto quit; + } + if (nets[0] == nets[1]) { + pcb_message(PCB_MSG_ERROR, "Those two pins are on the same net, can't swap them.\n"); + goto quit; + } + + + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pins[0], nets[0]->Name + 2, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_DEL_CONN, pins[1], nets[1]->Name + 2, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pins[0], nets[1]->Name + 2, NULL); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pins[1], nets[0]->Name + 2, 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) +{ + int ni, pi; + pcb_lib_t *netlist = patch ? &PCB->NetlistLib[PCB_NETLIST_EDITED] : &PCB->NetlistLib[PCB_NETLIST_INPUT]; + pcb_lib_menu_t *net = NULL; + pcb_lib_entry_t *pin = NULL; + + if ((netname == NULL) || (pinname == NULL)) + return -1; + + if ((*netname == '\0') || (*pinname == '\0')) + return -1; + + for (ni = 0; ni < netlist->MenuN; ni++) { + if (strcmp(netlist->Menu[ni].Name + 2, netname) == 0) { + net = &(netlist->Menu[ni]); + break; + } + } + + + if (net == NULL) { + if (!patch) { + net = pcb_lib_menu_new(netlist, NULL); + net->Name = pcb_strdup_printf(" %s", netname); + net->flag = 1; + PCB->netlist_needs_update=1; + } + else + net = pcb_lib_net_new(netlist, (char *) netname, NULL); + } + + for (pi = 0; pi < net->EntryN; pi++) { + if (strcmp(net->Entry[pi].ListEntry, pinname) == 0) { + pin = &(net->Entry[pi]); + break; + } + } + + + if (pin == NULL) { + if (!patch) { + pcb_lib_entry_t *entry = pcb_lib_entry_new(net); + entry->ListEntry = pcb_strdup_printf("%s", pinname); + entry->ListEntry_dontfree = 0; + PCB->netlist_needs_update=1; + } + else { + pin = pcb_lib_conn_new(net, (char *) pinname); + pcb_ratspatch_append_optimize(PCB, RATP_ADD_CONN, pin->ListEntry, net->Name + 2, NULL); + } + } + + pcb_netlist_changed(0); + return 0; +} + +static const char pcb_acts_Netlist[] = + "Net(find|select|rats|norats|clear[,net[,pin]])\n" "Net(freeze|thaw|forcethaw)\n" "Net(swap)\n" "Net(add,net,pin)"; + +static const char pcb_acth_Netlist[] = "Perform various actions on netlists."; + +/* %start-doc actions Netlist + +Each of these actions apply to a specified set of nets. @var{net} and +@var{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, +@emph{then} the pattern is tried as a regular expression. + +If neither @var{net} nor @var{pin} are specified, all nets apply. If +@var{net} is specified but not @var{pin}, all nets matching @var{net} +apply. If both are specified, nets which match @var{net} and contain +a pin matching @var{pin} apply. + +@table @code + +@item find +Nets which apply are marked @emph{found} and are drawn in the +@code{connected-color} color. + +@item select +Nets which apply are selected. + +@item rats +Nets which apply are marked as available for the rats nest. + +@item norats +Nets which apply are marked as not available for the rats nest. + +@item clear +Clears the netlist. + +@item add +Add the given pin to the given netlist, creating either if needed. + +@item swap +Swap the connections one end of two selected rats and pins. + +@item sort +Called after a list of add's, this sorts the netlist. + +@item freeze +@itemx thaw +@itemx 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. + +@end table + +%end-doc */ + +typedef void (*NFunc) (pcb_lib_menu_t *, pcb_lib_entry_t *); + +static int pcb_act_Netlist(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + NFunc func; + int i, j; + pcb_lib_menu_t *net; + pcb_lib_entry_t *pin; + int net_found = 0; + int pin_found = 0; + int use_re = 0; + re_sei_t *regex; + + if (!PCB) + return 1; + if (argc == 0) { + pcb_message(PCB_MSG_ERROR, pcb_acts_Netlist); + return 1; + } + if (pcb_strcasecmp(argv[0], "find") == 0) + func = pcb_netlist_find; + else if (pcb_strcasecmp(argv[0], "select") == 0) + func = pcb_netlist_select; + else if (pcb_strcasecmp(argv[0], "rats") == 0) + func = pcb_netlist_rats; + else if (pcb_strcasecmp(argv[0], "norats") == 0) + func = pcb_netlist_norats; + else if (pcb_strcasecmp(argv[0], "clear") == 0) { + func = pcb_netlist_clear; + if (argc == 1) { + pcb_netlist_clear(NULL, NULL); + return 0; + } + } + else if (pcb_strcasecmp(argv[0], "style") == 0) + func = (NFunc) pcb_netlist_style; + else if (pcb_strcasecmp(argv[0], "swap") == 0) + return pcb_netlist_swap(); + else if (pcb_strcasecmp(argv[0], "add") == 0) { + /* Add is different, because the net/pin won't already exist. */ + return pcb_netlist_add(0, PCB_ACTION_ARG(1), PCB_ACTION_ARG(2)); + } + else if (pcb_strcasecmp(argv[0], "sort") == 0) { + pcb_sort_netlist(); + pcb_ratspatch_make_edited(PCB); + return 0; + } + else if (pcb_strcasecmp(argv[0], "freeze") == 0) { + PCB->netlist_frozen++; + return 0; + } + else if (pcb_strcasecmp(argv[0], "thaw") == 0) { + if (PCB->netlist_frozen > 0) { + PCB->netlist_frozen--; + if (PCB->netlist_needs_update) + pcb_netlist_changed(0); + } + return 0; + } + else if (pcb_strcasecmp(argv[0], "forcethaw") == 0) { + PCB->netlist_frozen = 0; + if (PCB->netlist_needs_update) + pcb_netlist_changed(0); + return 0; + } + else { + pcb_message(PCB_MSG_ERROR, pcb_acts_Netlist); + return 1; + } + + if (argc > 1) { + use_re = 1; + for (i = 0; i < PCB->NetlistLib[PCB_NETLIST_INPUT].MenuN; i++) { + net = PCB->NetlistLib[PCB_NETLIST_INPUT].Menu + i; + if (pcb_strcasecmp(argv[1], net->Name + 2) == 0) + use_re = 0; + } + if (use_re) { + regex = re_sei_comp(argv[1]); + if (re_sei_errno(regex) != 0) { + pcb_message(PCB_MSG_ERROR, _("regexp error: %s\n"), re_error_str(re_sei_errno(regex))); + re_sei_free(regex); + return (1); + } + } + } + +/* This code is for changing the netlist style */ + for (i = PCB->NetlistLib[PCB_NETLIST_INPUT].MenuN - 1; i >= 0; i--) { + net = PCB->NetlistLib[PCB_NETLIST_INPUT].Menu + i; + + if (argc > 1) { + if (use_re) { + if (re_sei_exec(regex, net->Name + 2) == 0) + continue; + } + else { + if (pcb_strcasecmp(net->Name + 2, argv[1])) + continue; + } + } + net_found = 1; + + pin = 0; + if (func == (NFunc) pcb_netlist_style) { + pcb_netlist_style(net, PCB_ACTION_ARG(2)); + } + else if (argc > 2) { + int l = strlen(argv[2]); + for (j = net->EntryN - 1; j >= 0; j--) + if (pcb_strcasecmp(net->Entry[j].ListEntry, argv[2]) == 0 + || (pcb_strncasecmp(net->Entry[j].ListEntry, argv[2], l) == 0 && net->Entry[j].ListEntry[l] == '-')) { + pin = net->Entry + j; + pin_found = 1; + func(net, pin); + } + } + else + func(net, 0); + } + + if (argc > 2 && !pin_found) { + pcb_gui->log("Net %s has no pin %s\n", argv[1], argv[2]); + return 1; + } + else if (!net_found) { + pcb_gui->log("No net named %s\n", argv[1]); + } + + if (use_re) + re_sei_free(regex); + + return 0; +} + +pcb_hid_action_t netlist_action_list[] = { + {"net", 0, pcb_act_Netlist, + pcb_acth_Netlist, pcb_acts_Netlist} + , + {"netlist", 0, pcb_act_Netlist, + pcb_acth_Netlist, pcb_acts_Netlist} +}; + +PCB_REGISTER_ACTIONS(netlist_action_list, NULL) Index: tags/1.2.7/src/obj_all.h =================================================================== --- tags/1.2.7/src/obj_all.h (nonexistent) +++ tags/1.2.7/src/obj_all.h (revision 13657) @@ -0,0 +1,8 @@ +#include "obj_arc.h" +#include "obj_elem.h" +#include "obj_line.h" +#include "obj_pad.h" +#include "obj_pinvia.h" +#include "obj_poly.h" +#include "obj_text.h" +#include "obj_rat.h" Index: tags/1.2.7/src/obj_all_list.h =================================================================== --- tags/1.2.7/src/obj_all_list.h (nonexistent) +++ tags/1.2.7/src/obj_all_list.h (revision 13657) @@ -0,0 +1,9 @@ +#include "obj_arc_list.h" +#include "obj_elem_list.h" +#include "obj_line_list.h" +#include "obj_pad_list.h" +#include "obj_pstk_list.h" +#include "obj_pinvia_list.h" +#include "obj_poly_list.h" +#include "obj_text_list.h" +#include "obj_rat_list.h" Index: tags/1.2.7/src/obj_all_op.h =================================================================== --- tags/1.2.7/src/obj_all_op.h (nonexistent) +++ tags/1.2.7/src/obj_all_op.h (revision 13657) @@ -0,0 +1,9 @@ +#include "obj_arc_op.h" +#include "obj_elem_op.h" +#include "obj_line_op.h" +#include "obj_pad_op.h" +#include "obj_pinvia_op.h" +#include "obj_poly_op.h" +#include "obj_text_op.h" +#include "obj_rat_op.h" +#include "obj_subc_op.h" Index: tags/1.2.7/src/obj_any.c =================================================================== --- tags/1.2.7/src/obj_any.c (nonexistent) +++ tags/1.2.7/src/obj_any.c (revision 13657) @@ -0,0 +1,28 @@ +/* + * 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. + * + */ + +/* object model - type+union that can represent any object */ + +#define TDL_DONT_UNDEF +#include "config.h" +#include "obj_any.h" +#include Index: tags/1.2.7/src/obj_any.h =================================================================== --- tags/1.2.7/src/obj_any.h (nonexistent) +++ tags/1.2.7/src/obj_any.h (revision 13657) @@ -0,0 +1,75 @@ +/* + * 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. + * + */ + +/* object model - type+union that can represent any object */ + +#ifndef PCB_OBJ_H +#define PCB_OBJ_H + +#include "obj_common.h" +#include "global_typedefs.h" + + +typedef struct pcb_obj_s pcb_obj_t; + +struct pcb_obj_s { + pcb_objtype_t type; + union { + void *any; + pcb_any_obj_t *anyobj; + pcb_point_t *point; + pcb_line_t *line; + pcb_text_t *text; + pcb_poly_t *polygon; + pcb_arc_t *arc; + pcb_rat_t *rat; + pcb_pad_t *pad; + pcb_pin_t *pin; + pcb_pin_t *via; + pcb_pstk_t *pstk; + pcb_element_t *element; + pcb_net_t *net; + pcb_layer_t *layer; + pcb_subc_t *subc; + } data; + + pcb_parenttype_t parent_type; + pcb_parent_t parent; + gdl_elem_t link; +}; + + +/* List of objects */ +#define TDL(x) pcb_objlist_ ## x +#define TDL_LIST_T pcb_objlist_t +#define TDL_ITEM_T pcb_obj_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define pcb_objlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include +#include + +#endif Index: tags/1.2.7/src/obj_arc.c =================================================================== --- tags/1.2.7/src/obj_arc.c (nonexistent) +++ tags/1.2.7/src/obj_arc.c (revision 13657) @@ -0,0 +1,936 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: (elliptical) arc */ + + +#include "config.h" +#include "compat_nls.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 "obj_arc.h" +#include "obj_arc_op.h" + +#include "obj_subc_parent.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; + +pcb_arc_t *pcb_arc_alloc(pcb_layer_t * layer) +{ + pcb_arc_t *new_obj; + + new_obj = calloc(sizeof(pcb_arc_t), 1); + new_obj->type = PCB_OBJ_ARC; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, layer, layer); + arclist_append(&layer->Arc, new_obj); + + return new_obj; +} + +pcb_arc_t *pcb_element_arc_alloc(pcb_element_t *Element) +{ + pcb_arc_t *arc = calloc(sizeof(pcb_arc_t), 1); + + arc->type = PCB_OBJ_ARC; + PCB_SET_PARENT(arc, element, Element); + + arclist_append(&Element->Arc, arc); + return arc; +} + + + +/* 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); +} + + +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)); + } +} + +/* doesn't these belong in change.c ?? */ +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_TYPE_ARC, Layer, a); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_undo_add_obj_to_change_angles(PCB_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_ARC, Layer, a); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) a); + pcb_undo_add_obj_to_change_radii(PCB_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_arc_t *Arc; + + PCB_ARC_LOOP(Layer); + { + 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 */ + } + PCB_END_LOOP; + Arc = pcb_arc_alloc(Layer); + if (!Arc) + return (Arc); + + Arc->ID = pcb_create_ID_get(); + 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_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_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(NULL, 0, 0); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + Arc->type = PCB_OBJ_ARC; + PCB_SET_PARENT(Arc, layer, Layer); +} + + + +void pcb_arc_free(pcb_arc_t * data) +{ + arclist_remove(data); + free(data); +} + + +int pcb_arc_eq(const pcb_element_t *e1, const pcb_arc_t *a1, const pcb_element_t *e2, const pcb_arc_t *a2) +{ + 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_element_neq_offsx(e1, a1, e2, a2, X) || pcb_element_neq_offsy(e1, a1, e2, a2, Y)) return 0; + if (pcb_field_neq(a1, a2, StartAngle) || pcb_field_neq(a1, a2, Delta)) return 0; + + return 1; +} + +unsigned int pcb_arc_hash(const pcb_element_t *e, const pcb_arc_t *a) +{ + return + pcb_hash_coord(a->Thickness) ^ pcb_hash_coord(a->Clearance) ^ + pcb_hash_coord(a->Width) ^ pcb_hash_coord(a->Height) ^ + pcb_hash_element_ox(e, a->X) ^ pcb_hash_element_oy(e, a->Y) ^ + pcb_hash_coord(a->StartAngle) ^ pcb_hash_coord(a->Delta); +} + +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); +} + +/***** 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_arc_copy_meta(a, Arc); + return a; +} + +/* moves an arc to buffer */ +void *pcb_arcop_move_to_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_arc_t * arc) +{ + pcb_layer_t *lay = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, layer)]; + + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_ARC, layer, arc); + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *) arc); + + arclist_remove(arc); + arclist_append(&lay->Arc, arc); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, arc); + + if (!lay->arc_tree) + lay->arc_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(lay->arc_tree, (pcb_box_t *) arc, 0); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_ARC, lay, arc); + + PCB_SET_PARENT(arc, layer, lay); + + 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_TYPE_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_TYPE_ARC, Layer, Arc); + Arc->Thickness = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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 < PCB->Bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < PCB->Bloat * 2) + value = PCB->Bloat * 2 + 2; + if (value != Arc->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_TYPE_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_TYPE_ARC, Layer, Arc); + Arc->Clearance = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_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_TYPE_ARC, Layer, Arc); + *dst = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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; + value = fmod(value, 360.0); + + if (value != *dst) { + pcb_undo_add_obj_to_change_angles(PCB_TYPE_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_TYPE_ARC, Layer, Arc); + *dst = value; + pcb_arc_bbox(Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_ARC, Layer, Arc); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_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_TYPE_ARC, Layer, Arc); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_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)); + if (!arc) + return (arc); + pcb_arc_copy_meta(arc, Arc); + pcb_arc_invalidate_draw(Layer, arc); + pcb_undo_add_obj_to_create(PCB_TYPE_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); + pcb_draw(); + } + 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_TYPE_ARC, Layer, Arc); + pcb_arcop_move_noclip(ctx, Layer, Arc); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_ARC, Layer, Arc); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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); + + arclist_remove(arc); + arclist_append(&Destination->Arc, arc); + + if (!Destination->arc_tree) + Destination->arc_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Destination->arc_tree, (pcb_box_t *) arc, 0); + + PCB_SET_PARENT(arc, layer, Destination); + + 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, the object is locked\n")); + return NULL; + } + if (ctx->move.dst_layer == Layer && Layer->meta.real.vis) { + pcb_arc_invalidate_draw(Layer, Arc); + pcb_draw(); + } + if (ctx->move.dst_layer == Layer) + return (Arc); + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_ARC, Layer, Arc, Arc); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_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_TYPE_ARC, ctx->move.dst_layer, Arc); + if (ctx->move.dst_layer->meta.real.vis) + pcb_arc_invalidate_draw(ctx->move.dst_layer, newone); + pcb_draw(); + 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_CLEAR_PARENT(Arc); + pcb_arc_free(Arc); + + return NULL; +} + +/* removes an arc from a layer */ +void *pcb_arcop_remve(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); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_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_remve(ctx, l, a); +} + +void *pcb_arc_destroy(pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + return pcb_arcop_remve(&ctx, Layer, Arc); +} + +/* 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) +{ + 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); + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *) arc, 0); +} + +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, 0); +} + +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, 0); +} + +/* 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_TYPE_ARC, Layer, Arc); + 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); + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_ARC, Layer, Arc); + pcb_arc_invalidate_draw(Layer, Arc); + pcb_draw(); + 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_TYPE_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_TYPE_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); + 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_arc_copy_meta(new_arc, arc); + + if (new_arc != NULL) { + 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_TYPE_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_TYPE_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_TYPE_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_setup(&text, x0, y0, 100.0, vert, pcb_true, arc->term, arc->intconn); + pcb_draw_invalidate(&text); + } +} + +void pcb_arc_draw_label(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(x0, y0, 100.0, vert, pcb_true, arc->term, arc->intconn); + } +} + +void pcb_arc_draw_(pcb_arc_t * arc, int allow_term_gfx) +{ + if (!arc->Thickness) + return; + + 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_gui->set_line_width(pcb_draw_out.active_padGC, arc->Thickness); + pcb_gui->draw_arc(pcb_draw_out.active_padGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + pcb_gui->set_line_width(pcb_draw_out.fgGC, PCB_DRAW_TERM_GFX_WIDTH); + } + else + pcb_gui->set_line_width(pcb_draw_out.fgGC, arc->Thickness); + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Trace_Cap); + pcb_gui->draw_arc(pcb_draw_out.fgGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + } + else + { + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Trace_Cap); + + 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); + } + if (arc->term != NULL) { + if ((pcb_draw_doing_pinout) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, arc)) + pcb_draw_delay_label_add((pcb_any_obj_t *)arc); + } +} + +static void pcb_arc_draw(pcb_layer_t * layer, pcb_arc_t * arc, int allow_term_gfx) +{ + const char *color; + char buf[sizeof("#XXXXXX")]; + + 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)) + color = layer->meta.real.selected_color; + 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); + else + color = layer->meta.real.color; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, arc)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + pcb_gui->set_color(pcb_draw_out.fgGC, color); + pcb_arc_draw_(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; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(arc->parent_type, &arc->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_arc_draw((pcb_layer_t *)cl, 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; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(arc->parent_type, &arc->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_arc_draw((pcb_layer_t *)cl, 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/1.2.7/src/obj_arc.h =================================================================== --- tags/1.2.7/src/obj_arc.h (nonexistent) +++ tags/1.2.7/src/obj_arc.h (revision 13657) @@ -0,0 +1,130 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: (elliptical) arc */ + +#ifndef PCB_OBJ_ARC_H +#define PCB_OBJ_ARC_H + +#include "obj_common.h" + +struct pcb_arc_s { /* holds information about arcs */ + PCB_ANYOBJECTFIELDS; + 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_element_arc_alloc(pcb_element_t *Element); +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_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); + +/* 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); +pcb_box_t pcb_arc_mini_bbox(const pcb_arc_t *arc); + + +/*** hash ***/ +int pcb_arc_eq(const pcb_element_t *e1, const pcb_arc_t *a1, const pcb_element_t *e2, const pcb_arc_t *a2); +unsigned int pcb_arc_hash(const pcb_element_t *e, 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; + + +#define pcb_arc_move(a,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_arc_t *__a__ = (a); \ + PCB_MOVE((__a__)->X,(__a__)->Y,__dx__,__dy__) \ + PCB_BOX_MOVE_LOWLEVEL(&((__a__)->BoundingBox),__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/1.2.7/src/obj_arc_draw.h =================================================================== --- tags/1.2.7/src/obj_arc_draw.h (nonexistent) +++ tags/1.2.7/src/obj_arc_draw.h (revision 13657) @@ -0,0 +1,40 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw of arcs ***/ + +/* 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_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_arc_t *arc); + Index: tags/1.2.7/src/obj_arc_list.c =================================================================== --- tags/1.2.7/src/obj_arc_list.c (nonexistent) +++ tags/1.2.7/src/obj_arc_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_arc_list.h" +#include Index: tags/1.2.7/src/obj_arc_list.h =================================================================== --- tags/1.2.7/src/obj_arc_list.h (nonexistent) +++ tags/1.2.7/src/obj_arc_list.h (revision 13657) @@ -0,0 +1,44 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_arc_op.h =================================================================== --- tags/1.2.7/src/obj_arc_op.h (nonexistent) +++ tags/1.2.7/src/obj_arc_op.h (revision 13657) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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_to_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_remve(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/1.2.7/src/obj_arc_ui.c =================================================================== --- tags/1.2.7/src/obj_arc_ui.c (nonexistent) +++ tags/1.2.7/src/obj_arc_ui.c (revision 13657) @@ -0,0 +1,136 @@ +/* + * 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. + * + */ + +/* 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/1.2.7/src/obj_arc_ui.h =================================================================== --- tags/1.2.7/src/obj_arc_ui.h (nonexistent) +++ tags/1.2.7/src/obj_arc_ui.h (revision 13657) @@ -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. + * + */ +/* 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/1.2.7/src/obj_common.c =================================================================== --- tags/1.2.7/src/obj_common.c (nonexistent) +++ tags/1.2.7/src/obj_common.c (revision 13657) @@ -0,0 +1,203 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* functions used to create vias, pins ... */ + +#include "config.h" + +#include +#include +#include "conf_core.h" +#include "flag_str.h" +#include "global_typedefs.h" +#include "const.h" +#include "error.h" +#include "obj_common.h" +#include "obj_arc_ui.h" + +const char *pcb_obj_type_name(pcb_objtype_t type) +{ + switch(type) { + case PCB_OBJ_VOID: return "void"; + case PCB_OBJ_POINT: return "point"; + 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_PAD: return "pad"; + case PCB_OBJ_PIN: return "pin"; + case PCB_OBJ_VIA: return "via"; + case PCB_OBJ_PSTK: return "padstack"; + case PCB_OBJ_ELEMENT: return "element"; + case PCB_OBJ_SUBC: return "subcircuit"; + case PCB_OBJ_NET: return "net"; + case PCB_OBJ_LAYER: return "layer"; + case PCB_OBJ_ELINE: + case PCB_OBJ_EARC: + case PCB_OBJ_ETEXT: + break; + } + return ""; +} + +/* returns a pointer to an objects bounding box; + * data is valid until the routine is called again + */ +int GetObjectBoundingBox(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res) +{ + switch (Type) { + case PCB_TYPE_LINE: + case PCB_TYPE_ARC: + case PCB_TYPE_TEXT: + case PCB_TYPE_POLY: + case PCB_TYPE_PAD: + case PCB_TYPE_PIN: + case PCB_TYPE_PSTK: + case PCB_TYPE_ELEMENT_NAME: + *res = *(pcb_box_t *)Ptr2; + return 0; + case PCB_TYPE_VIA: + case PCB_TYPE_ELEMENT: + case PCB_TYPE_SUBC: + *res = *(pcb_box_t *)Ptr1; + return 0; + case PCB_TYPE_POLY_POINT: + case PCB_TYPE_LINE_POINT: + *res = *(pcb_box_t *)Ptr3; + return 0; + case PCB_TYPE_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; + +/* --------------------------------------------------------------------------- + * Set the lenience mode. + */ +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_PIN: + *x = ((const pcb_pin_t *)(obj))->X; + *y = ((const pcb_pin_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 subc refdes '%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; + } +} + +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 ':': continue; + } + return s; + } + return NULL; +} + +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; +} Index: tags/1.2.7/src/obj_common.h =================================================================== --- tags/1.2.7/src/obj_common.h (nonexistent) +++ tags/1.2.7/src/obj_common.h (revision 13657) @@ -0,0 +1,238 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_OBJ_COMMON_H +#define PCB_OBJ_COMMON_H + +#include +#include +#include +#include "flag.h" +#include "attrib.h" +#include "global_typedefs.h" +#include "data_parent.h" + +/* Can be used as a bitfield */ +typedef enum pcb_objtype_e { + PCB_OBJ_VOID = 0x000000, + + PCB_OBJ_POINT = 0x000001, + PCB_OBJ_LINE = 0x000002, + PCB_OBJ_TEXT = 0x000004, + PCB_OBJ_POLY = 0x000008, + PCB_OBJ_ARC = 0x000010, + PCB_OBJ_RAT = 0x000020, + PCB_OBJ_PAD = 0x000040, + PCB_OBJ_PIN = 0x000080, + PCB_OBJ_VIA = 0x000100, + PCB_OBJ_ELEMENT = 0x000200, + PCB_OBJ_SUBC = 0x000400, + PCB_OBJ_PSTK = 0x000800, + + /* more abstract objects */ + PCB_OBJ_NET = 0x100001, + PCB_OBJ_LAYER = 0x100002, + + /* temporary, for backward compatibility */ + PCB_OBJ_ELINE = 0x200001, + PCB_OBJ_EARC = 0x200002, + PCB_OBJ_ETEXT = 0x200004 +} pcb_objtype_t; + +/* combinations, groups, masks of pcb_objtype_t */ +typedef enum pcb_objmask_e { + PCB_OBJ_CLASS_MASK= 0xF00000, + PCB_OBJ_CLASS_OBJ = 0x000000, /* anything with common object fields (pcb_any_obj_t) */ + PCB_OBJ_CLASS_REAL= 0x000FFF, /* global and on-layer objects (but not abstract things like layers) */ + PCB_OBJ_ANY = 0xFFFFFF +} 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 */ +}; + +/* 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 GetObjectBoundingBox(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_box_t *res); + +/* 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 uses the "object flags" defined in const.h, or + exists as an object on the pcb, MUST be defined using this as the + first fields, either directly or through PCB_ANYLINEFIELDS. */ +#define PCB_ANYOBJECTFIELDS \ + pcb_box_t BoundingBox; \ + long int ID; \ + pcb_flag_t Flags; \ + pcb_objtype_t type; \ + pcb_parenttype_t parent_type; \ + pcb_parent_t parent; \ + const char *term; \ + void *ratconn; \ + unsigned char thermal; \ + unsigned char intconn; \ + pcb_attribute_list_t Attributes; \ + char override_color[sizeof("#XXXXXX")] + +/* Lines, pads, and rats all use this so they can be cross-cast. */ +#define PCB_ANYLINEFIELDS \ + PCB_ANYOBJECTFIELDS; \ + 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_ANYOBJECTFIELDS; +}; + +/* Lines, rats, pads, etc. */ +struct pcb_any_line_s { + PCB_ANYLINEFIELDS; +}; + +/*** Functions and macros used for hashing ***/ + +/* 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)); +} + +/* 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); + +/* 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); + +/* 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 */ +#define PCB_OBJ_COLOR_ON_BOUND_LAYER(dst, layer) \ +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) { \ + 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)) { \ + dst = conf_core.appearance.color.layer[lid]; \ + break; \ + } \ + } \ + dst = conf_core.appearance.color.invisible_objects; \ +} while(0) + +/* compare two fields and return 0 if they are equal */ +#define pcb_field_neq(s1, s2, f) ((s1)->f != (s2)->f) + +/* hash relative x and y within an element */ +#define pcb_hash_element_ox(e, c) ((e) == NULL ? pcb_hash_coord(c) : pcb_hash_coord(c - e->MarkX)) +#define pcb_hash_element_oy(e, c) ((e) == NULL ? pcb_hash_coord(c) : pcb_hash_coord(c - e->MarkY)) + +#define pcb_hash_str(s) ((s) == NULL ? 0 : strhash(s)) + +#define pcb_element_offs(e,ef, s,sf) ((e == NULL) ? (s)->sf : ((s)->sf) - ((e)->ef)) +#define pcb_element_neq_offsx(e1, x1, e2, x2, f) (pcb_element_offs(e1, MarkX, x1, f) != pcb_element_offs(e2, MarkX, x2, f)) +#define pcb_element_neq_offsy(e1, y1, e2, y2, f) (pcb_element_offs(e1, MarkY, y1, f) != pcb_element_offs(e2, MarkY, y2, f)) + + +/* 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[0] == '#') \ + ) + +#endif Index: tags/1.2.7/src/obj_elem.c =================================================================== --- tags/1.2.7/src/obj_elem.c (nonexistent) +++ tags/1.2.7/src/obj_elem.c (revision 13657) @@ -0,0 +1,2077 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: elements */ + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "list_common.h" +#include "plug_io.h" +#include "conf_core.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "rotate.h" +#include "remove.h" +#include "polygon.h" +#include "undo.h" +#include "obj_pinvia_op.h" +#include "obj_pad_op.h" + +#include "obj_pinvia_draw.h" +#include "obj_pad_draw.h" +#include "obj_line_draw.h" +#include "obj_arc_draw.h" + +#include "obj_elem.h" +#include "obj_elem_list.h" +#include "obj_elem_op.h" +#include "obj_subc_list.h" + +/* TODO: remove this: */ +#include "draw.h" +#include "obj_text_draw.h" +#include "obj_elem_draw.h" + +/*** allocation ***/ + +/* get next slot for an element, allocates memory if necessary */ +pcb_element_t *pcb_element_alloc(pcb_data_t * data) +{ + pcb_element_t *new_obj; + int n; + + new_obj = calloc(sizeof(pcb_element_t), 1); + new_obj->type = PCB_OBJ_ELEMENT; + PCB_SET_PARENT(new_obj, data, data); + + for(n = 0; n < PCB_MAX_ELEMENTNAMES; n++) { + new_obj->Name[n].type = PCB_OBJ_ETEXT; + PCB_SET_PARENT(&new_obj->Name[n], element, new_obj); + } + + elementlist_append(&data->Element, new_obj); + + return new_obj; +} + +void pcb_element_free(pcb_element_t * data) +{ + elementlist_remove(data); + free(data); +} + +/* frees memory used by an element */ +void pcb_element_destroy(pcb_element_t * element) +{ + if (element == NULL) + return; + + PCB_ELEMENT_NAME_LOOP(element); + { + free(textstring); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + free(pin->Name); + free(pin->Number); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + free(pad->Name); + free(pad->Number); + } + PCB_END_LOOP; + + list_map0(&element->Pin, pcb_pin_t, pcb_pin_free); + list_map0(&element->Pad, pcb_pad_t, pcb_pad_free); + list_map0(&element->Line, pcb_line_t, pcb_line_free); + list_map0(&element->Arc, pcb_arc_t, pcb_arc_free); + + pcb_attribute_free(&element->Attributes); + reset_obj_mem(pcb_element_t, element); +} + +pcb_line_t *pcb_element_line_alloc(pcb_element_t *Element) +{ + pcb_line_t *line = calloc(sizeof(pcb_line_t), 1); + + line->type = PCB_OBJ_ELINE; + PCB_SET_PARENT(line, element, Element); + + linelist_append(&Element->Line, line); + + return line; +} + +/*** utility ***/ +/* loads element data from file/library into buffer + * parse the file with disabled 'PCB mode' (see parser) + * returns pcb_false on error + * if successful, update some other stuff and reposition the pastebuffer + */ +pcb_bool pcb_element_load_to_buffer(pcb_buffer_t *Buffer, const char *Name) +{ + pcb_buffer_clear(PCB, Buffer); + if (!pcb_parse_element(Buffer->Data, Name)) { + 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 (elementlist_length(&Buffer->Data->Element)) { + pcb_element_t *element = elementlist_first(&Buffer->Data->Element); + Buffer->X = element->MarkX; + Buffer->Y = element->MarkY; + } + else 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); +} + + +/* Searches for the given element by "footprint" name, and loads it + into the buffer. Returns zero on success, non-zero on error. */ +int pcb_element_load_footprint_by_name(pcb_buffer_t *Buffer, const char *Footprint) +{ + return !pcb_element_load_to_buffer(Buffer, Footprint); +} + + +/* break buffer element into pieces */ +pcb_bool pcb_element_smash_buffer(pcb_buffer_t *Buffer) +{ + pcb_element_t *element; + pcb_layergrp_id_t group, gbottom, gtop; + pcb_layer_t *clayer, *slayer; + char tmp[128]; + + if (elementlist_length(&Buffer->Data->Element) != 1) + return (pcb_false); + + /* + * At this point the buffer should contain just a single element. + * Now we detach the single element from the buffer and then clear the + * buffer, ready to receive the smashed elements. As a result of detaching + * it the single element is orphaned from the buffer and thus will not be + * free()'d by pcb_data_free(called via ClearBuffer). This leaves it + * around for us to smash bits off it. It then becomes our responsibility, + * however, to free the single element when we're finished with it. + */ + element = elementlist_first(&Buffer->Data->Element); + elementlist_remove(element); + pcb_buffer_clear(PCB, Buffer); + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + pcb_line_new(&Buffer->Data->SILKLAYER, + line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness, 0, pcb_no_flags()); + if (line) + line->Number = pcb_strdup_null(PCB_ELEM_NAME_REFDES(element)); + } + PCB_END_LOOP; + PCB_ARC_LOOP(element); + { + pcb_arc_new(&Buffer->Data->SILKLAYER, + arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness, 0, pcb_no_flags()); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + pcb_pin_t *via; + pcb_flag_t f = pcb_no_flags(); + pcb_flag_add(f, PCB_FLAG_VIA); + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) + f = pcb_flag_add(f, PCB_FLAG_HOLE); + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) + f = pcb_flag_add(f, PCB_FLAG_SQUARE); + if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pin)) + f = pcb_flag_add(f, PCB_FLAG_OCTAGON); + + via = pcb_via_new(Buffer->Data, pin->X, pin->Y, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Number, f); + if (pin->Number != NULL) + pcb_attribute_put(&via->Attributes, "term", pin->Number); + if (pin->Flags.q != 0) { + char tmp[16]; + sprintf(tmp, "%d", pin->Flags.q); + pcb_attribute_put(&via->Attributes, "elem_smash_shape_id", tmp); + } + pcb_attribute_put(&via->Attributes, "elem_smash_pad", "1"); + pcb_sprintf(tmp, "%$mm", pin->Mask); + pcb_attribute_put(&pin->Attributes, "elem_smash_pad_mask", tmp); + } + PCB_END_LOOP; + + gbottom = gtop = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &gbottom, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, >op, 1); + + group = (PCB_SWAP_IDENT ? gbottom : gtop); + clayer = &Buffer->Data->Layer[PCB->LayerGroups.grp[group].lid[0]]; + group = (PCB_SWAP_IDENT ? gtop : gbottom); + slayer = &Buffer->Data->Layer[PCB->LayerGroups.grp[group].lid[0]]; + PCB_PAD_LOOP(element); + { + pcb_line_t *line; + line = pcb_line_new(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? slayer : clayer, + pad->Point1.X, pad->Point1.Y, + pad->Point2.X, pad->Point2.Y, pad->Thickness, pad->Clearance, pcb_no_flags()); + if (line) { + line->Number = pcb_strdup_null(pad->Number); + if (pad->Number != NULL) + pcb_attribute_put(&line->Attributes, "term", pad->Number); + if (pad->Flags.q != 0) { + char tmp[16]; + sprintf(tmp, "%d", pad->Flags.q); + pcb_attribute_put(&line->Attributes, "elem_smash_shape_id", tmp); + } + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad)) + pcb_attribute_put(&line->Attributes, "elem_smash_shape_square", "1"); + if (PCB_FLAG_TEST(PCB_FLAG_NOPASTE, pad)) + pcb_attribute_put(&line->Attributes, "elem_smash_nopaste", "1"); + pcb_attribute_put(&line->Attributes, "elem_smash_pad", "1"); + pcb_sprintf(tmp, "%$mm", pad->Mask); + pcb_attribute_put(&line->Attributes, "elem_smash_pad_mask", tmp); + } + } + PCB_END_LOOP; + pcb_element_destroy(element); + pcb_element_free(element); + return (pcb_true); +} + +/* see if a polygon is a rectangle. If so, canonicalize it. */ +static int polygon_is_rectangle(pcb_poly_t *poly) +{ + int i, best; + pcb_point_t temp[4]; + if (poly->PointN != 4 || poly->HoleIndexN != 0) + return 0; + best = 0; + for (i = 1; i < 4; i++) + if (poly->Points[i].X < poly->Points[best].X || poly->Points[i].Y < poly->Points[best].Y) + best = i; + for (i = 0; i < 4; i++) + temp[i] = poly->Points[(i + best) % 4]; + if (temp[0].X == temp[1].X) + memcpy(poly->Points, temp, sizeof(temp)); + else { + /* reverse them */ + poly->Points[0] = temp[0]; + poly->Points[1] = temp[3]; + poly->Points[2] = temp[2]; + poly->Points[3] = temp[1]; + } + if (poly->Points[0].X == poly->Points[1].X + && poly->Points[1].Y == poly->Points[2].Y + && poly->Points[2].X == poly->Points[3].X && poly->Points[3].Y == poly->Points[0].Y) + return 1; + return 0; +} + +/* convert buffer contents into an element */ +pcb_bool pcb_element_convert_from_buffer(pcb_buffer_t *Buffer) +{ + pcb_element_t *Element; + pcb_layergrp_id_t gbottom, gtop; + pcb_cardinal_t pin_n = 1; + pcb_bool hasParts = pcb_false, crooked = pcb_false; + int onsolder; + pcb_bool warned = pcb_false; + + gbottom = gtop = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &gbottom, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, >op, 1); + + Element = pcb_element_new(PCB->Data, NULL, pcb_font(PCB, 0, 1), pcb_no_flags(), + NULL, NULL, NULL, PCB_PASTEBUFFER->X, + PCB_PASTEBUFFER->Y, 0, 100, pcb_flag_make(PCB_SWAP_IDENT ? PCB_FLAG_ONSOLDER : PCB_FLAG_NO), pcb_false); + if (!Element) + return (pcb_false); + PCB_VIA_LOOP(Buffer->Data); + { + char num[8]; + if (via->Mask < via->Thickness) + via->Mask = via->Thickness + 2 * PCB_MASKFRAME; + if (via->Name) + pcb_element_pin_new(Element, via->X, via->Y, via->Thickness, + via->Clearance, via->Mask, via->DrillingHole, + NULL, via->Name, pcb_flag_mask(via->Flags, PCB_FLAG_VIA | PCB_FLAG_FOUND | PCB_FLAG_SELECTED | PCB_FLAG_WARN)); + else { + sprintf(num, "%d", pin_n++); + pcb_element_pin_new(Element, via->X, via->Y, via->Thickness, + via->Clearance, via->Mask, via->DrillingHole, + NULL, num, pcb_flag_mask(via->Flags, PCB_FLAG_VIA | PCB_FLAG_FOUND | PCB_FLAG_SELECTED | PCB_FLAG_WARN)); + } + hasParts = pcb_true; + } + PCB_END_LOOP; + + for (onsolder = 0; onsolder < 2; onsolder++) { + pcb_layergrp_id_t side_grp; + int onsolderflag; + + if ((!onsolder) == (!PCB_SWAP_IDENT)) { + side_grp = gtop; + onsolderflag = PCB_FLAG_NO; + } + else { + side_grp = gbottom; + onsolderflag = PCB_FLAG_ONSOLDER; + } + +#define MAYBE_WARN() \ + if (onsolder && !hasParts && !warned) \ + { \ + warned = pcb_true; \ + pcb_message \ + (PCB_MSG_WARNING, _("Warning: All of the pads are on the opposite\n" \ + "side from the component - that's probably not what\n" \ + "you wanted\n")); \ + } \ + + /* get the side SM pads on the side we are dealing with (first component then solder) */ + PCB_COPPER_GROUP_LOOP(Buffer->Data, side_grp); + { + char num[8]; + PCB_LINE_LOOP(layer); + { + sprintf(num, "%d", pin_n++); + pcb_element_pad_new(Element, line->Point1.X, + line->Point1.Y, line->Point2.X, + line->Point2.Y, line->Thickness, + line->Clearance, + line->Thickness + line->Clearance, NULL, line->Number ? line->Number : num, pcb_flag_make(onsolderflag)); + MAYBE_WARN(); + hasParts = pcb_true; + } + PCB_END_LOOP; + PCB_POLY_LOOP(layer); + { + if (!polygon_is_rectangle(polygon)) { + crooked = pcb_true; + continue; + } + + sprintf(num, "%d", pin_n++); + + pcb_element_pad_new_rect(Element, + polygon->Points[2].X, polygon->Points[1].Y, + polygon->Points[0].X, polygon->Points[0].Y, + conf_core.design.clearance, conf_core.design.clearance, + NULL, num, pcb_flag_make(PCB_FLAG_SQUARE | onsolderflag)); + + MAYBE_WARN(); + hasParts = pcb_true; + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + + /* now add the silkscreen. NOTE: elements must have pads or pins too */ + PCB_LINE_LOOP(&Buffer->Data->SILKLAYER); + { + if (line->Number && !PCB_ELEM_NAME_REFDES(Element)) + PCB_ELEM_NAME_REFDES(Element) = pcb_strdup(line->Number); + pcb_element_line_new(Element, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y, line->Thickness); + hasParts = pcb_true; + } + PCB_END_LOOP; + PCB_ARC_LOOP(&Buffer->Data->SILKLAYER); + { + pcb_element_arc_new(Element, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); + hasParts = pcb_true; + } + PCB_END_LOOP; + if (!hasParts) { + pcb_destroy_object(PCB->Data, PCB_TYPE_ELEMENT, Element, Element, Element); + pcb_message(PCB_MSG_ERROR, _("There was nothing to convert!\n" "Elements must have some silk, pads or pins.\n")); + return (pcb_false); + } + if (crooked) + pcb_message(PCB_MSG_ERROR, _("There were polygons that can't be made into pins!\n" "So they were not included in the element\n")); + Element->MarkX = Buffer->X; + Element->MarkY = Buffer->Y; + if (PCB_SWAP_IDENT) + PCB_FLAG_SET(PCB_FLAG_ONSOLDER, Element); + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_buffer_clear(PCB, Buffer); + pcb_move_obj_to_buffer(PCB, Buffer->Data, PCB->Data, PCB_TYPE_ELEMENT, Element, Element, Element); + pcb_set_buffer_bbox(Buffer); + return (pcb_true); +} + +void pcb_element_rotate(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, pcb_angle_t angle) +{ + /* solder side objects need a different orientation */ + + /* the text subroutine decides by itself if the direction + * is to be corrected + */ + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + 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); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + /* pre-delete the pins from the pin-tree before their coordinates change */ + if (Data) + pcb_r_delete_entry(Data->pin_tree, (pcb_box_t *) pin); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PIN, Element, pin); + pcb_rotate(&pin->X, &pin->Y, X, Y, cosa, sina); + pcb_pin_bbox(pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + /* pre-delete the pads before their coordinates change */ + if (Data) + pcb_r_delete_entry(Data->pad_tree, (pcb_box_t *) pad); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PAD, Element, pad); + pcb_rotate(&pad->Point1.X, &pad->Point1.Y, X, Y, cosa, sina); + pcb_rotate(&pad->Point2.X, &pad->Point2.Y, X, Y, cosa, sina); + pcb_line_bbox((pcb_line_t *) pad); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_rotate(&arc->X, &arc->Y, X, Y, cosa, sina); + arc->StartAngle = pcb_normalize_angle(arc->StartAngle + angle); + } + PCB_END_LOOP; + + pcb_rotate(&Element->MarkX, &Element->MarkY, X, Y, cosa, sina); + pcb_element_bbox(Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(Data, PCB_TYPE_ELEMENT, Element, Element); +} + +/* changes the side of the board an element is on; returns pcb_true if done */ +pcb_bool pcb_element_change_side(pcb_element_t *Element, pcb_coord_t yoff) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (pcb_false); + pcb_elem_invalidate_erase(Element); + pcb_undo_add_obj_to_mirror(PCB_TYPE_ELEMENT, Element, Element, Element, yoff); + pcb_element_mirror(PCB->Data, Element, yoff); + pcb_elem_invalidate_draw(Element); + return (pcb_true); +} + +/* changes the side of all selected and visible elements; + returns pcb_true if anything has changed */ +pcb_bool pcb_selected_element_change_side(void) +{ + pcb_bool change = pcb_false; + + if (PCB->PinOn && pcb_silk_on(PCB)) + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + change |= pcb_element_change_side(element, 0); + } + } + PCB_END_LOOP; + return (change); +} + +/* changes the layout-name of an element */ +char *pcb_element_text_change(pcb_board_t * pcb, pcb_data_t * data, pcb_element_t *Element, int which, char *new_name) +{ + char *old = Element->Name[which].TextString; + + Element->Name[which].type = PCB_OBJ_ETEXT; + PCB_SET_PARENT(&Element->Name[which], element, Element); +#ifdef DEBUG + printf("In ChangeElementText, updating old TextString %s to %s\n", old, new_name); +#endif + + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_erase(Element); + + pcb_r_delete_entry(data->name_tree[which], &Element->Name[which].BoundingBox); + + Element->Name[which].TextString = new_name; + pcb_text_bbox(pcb_font(PCB, 0, 1), &Element->Name[which]); + + pcb_r_insert_entry(data->name_tree[which], &Element->Name[which].BoundingBox, 0); + + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_draw(Element); + + return old; +} + +void pcb_element_text_update(pcb_board_t *pcb, pcb_data_t *data, pcb_element_t *Element, int which) +{ + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_erase(Element); + + pcb_r_delete_entry(data->name_tree[which], &Element->Name[which].BoundingBox); + pcb_text_bbox(pcb_font(PCB, 0, 1), &Element->Name[which]); + pcb_r_insert_entry(data->name_tree[which], &Element->Name[which].BoundingBox, 0); + + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_draw(Element); +} + +void pcb_element_text_set_font(pcb_board_t *pcb, pcb_data_t *data, pcb_element_t *Element, int which, pcb_font_id_t fid) +{ + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_erase(Element); + + pcb_r_delete_entry(data->name_tree[which], &Element->Name[which].BoundingBox); + Element->Name[which].fid = fid; + pcb_text_bbox(pcb_font(PCB, 0, 1), &Element->Name[which]); + pcb_r_insert_entry(data->name_tree[which], &Element->Name[which].BoundingBox, 0); + + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + pcb_elem_name_invalidate_draw(Element); +} + +/* copies data from one element to another and creates the destination; if necessary */ +pcb_element_t *pcb_element_copy(pcb_data_t *Data, pcb_element_t *Dest, pcb_element_t *Src, pcb_bool uniqueName, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + /* release old memory if necessary */ + if (Dest) + pcb_element_destroy(Dest); + + /* both coordinates and flags are the same */ + Dest = pcb_element_new(Data, Dest, pcb_font(PCB, 0, 1), + pcb_flag_mask(Src->Flags, PCB_FLAG_FOUND), + PCB_ELEM_NAME_DESCRIPTION(Src), PCB_ELEM_NAME_REFDES(Src), + PCB_ELEM_NAME_VALUE(Src), PCB_ELEM_TEXT_DESCRIPTION(Src).X + dx, + PCB_ELEM_TEXT_DESCRIPTION(Src).Y + dy, + PCB_ELEM_TEXT_DESCRIPTION(Src).Direction, + PCB_ELEM_TEXT_DESCRIPTION(Src).Scale, pcb_flag_mask(PCB_ELEM_TEXT_DESCRIPTION(Src).Flags, PCB_FLAG_FOUND), uniqueName); + + /* abort on error */ + if (!Dest) + return (Dest); + + PCB_ELEMENT_PCB_LINE_LOOP(Src); + { + pcb_element_line_new(Dest, line->Point1.X + dx, + line->Point1.Y + dy, line->Point2.X + dx, line->Point2.Y + dy, line->Thickness); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Src); + { + pcb_element_pin_new(Dest, pin->X + dx, pin->Y + dy, pin->Thickness, + pin->Clearance, pin->Mask, pin->DrillingHole, pin->Name, pin->Number, pcb_flag_mask(pin->Flags, PCB_FLAG_FOUND)); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Src); + { + pcb_element_pad_new(Dest, pad->Point1.X + dx, pad->Point1.Y + dy, + pad->Point2.X + dx, pad->Point2.Y + dy, pad->Thickness, + pad->Clearance, pad->Mask, pad->Name, pad->Number, pcb_flag_mask(pad->Flags, PCB_FLAG_FOUND)); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Src); + { + pcb_element_arc_new(Dest, arc->X + dx, arc->Y + dy, arc->Width, arc->Height, arc->StartAngle, arc->Delta, arc->Thickness); + } + PCB_END_LOOP; + + for (i = 0; i < Src->Attributes.Number; i++) + pcb_attribute_put(&Dest->Attributes, Src->Attributes.List[i].name, Src->Attributes.List[i].value); + + Dest->MarkX = Src->MarkX + dx; + Dest->MarkY = Src->MarkY + dy; + + pcb_element_bbox(Data, Dest, pcb_font(PCB, 0, 1)); + return (Dest); +} + +/* creates an new element; memory is allocated if needed */ +pcb_element_t *pcb_element_new(pcb_data_t *Data, pcb_element_t *Element, + pcb_font_t *PCBFont, pcb_flag_t Flags, char *Description, char *NameOnPCB, + char *Value, pcb_coord_t TextX, pcb_coord_t TextY, pcb_uint8_t Direction, + int TextScale, pcb_flag_t TextFlags, pcb_bool uniqueName) +{ +#ifdef DEBUG + printf("Entered CreateNewElement.....\n"); +#endif + + if (!Element) + Element = pcb_element_alloc(Data); + + /* copy values and set additional information */ + TextScale = MAX(PCB_MIN_TEXTSCALE, TextScale); + pcb_element_text_set(&PCB_ELEM_TEXT_DESCRIPTION(Element), PCBFont, TextX, TextY, Direction, Description, TextScale, TextFlags); + if (uniqueName) + NameOnPCB = pcb_element_uniq_name(Data, NameOnPCB); + pcb_element_text_set(&PCB_ELEM_TEXT_REFDES(Element), PCBFont, TextX, TextY, Direction, NameOnPCB, TextScale, TextFlags); + pcb_element_text_set(&PCB_ELEM_TEXT_VALUE(Element), PCBFont, TextX, TextY, Direction, Value, TextScale, TextFlags); + PCB_ELEM_TEXT_DESCRIPTION(Element).Element = Element; + PCB_ELEM_TEXT_REFDES(Element).Element = Element; + PCB_ELEM_TEXT_VALUE(Element).Element = Element; + Element->Flags = Flags; + Element->ID = pcb_create_ID_get(); + +#ifdef DEBUG + printf(" .... Leaving CreateNewElement.\n"); +#endif + + return (Element); +} + +/* creates a new arc in an element */ +pcb_arc_t *pcb_element_arc_new(pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, + pcb_coord_t Width, pcb_coord_t Height, pcb_angle_t angle, pcb_angle_t delta, pcb_coord_t Thickness) +{ + pcb_arc_t *arc = pcb_element_arc_alloc(Element); + + /* set Delta (0,360], StartAngle in [0,360) */ + if (delta < 0) { + delta = -delta; + angle -= delta; + } + angle = pcb_normalize_angle(angle); + delta = pcb_normalize_angle(delta); + if (delta == 0) + delta = 360; + + /* copy values */ + arc->X = X; + arc->Y = Y; + arc->Width = Width; + arc->Height = Height; + arc->StartAngle = angle; + arc->Delta = delta; + arc->Thickness = Thickness; + arc->ID = pcb_create_ID_get(); + return arc; +} + +/* creates a new line for an element */ +pcb_line_t *pcb_element_line_new(pcb_element_t *Element, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness) +{ + pcb_line_t *line; + + if (Thickness == 0) + return NULL; + + line = pcb_element_line_alloc(Element); + + /* copy values */ + line->Point1.X = X1; + line->Point1.Y = Y1; + line->Point2.X = X2; + line->Point2.Y = Y2; + line->Thickness = Thickness; + line->Flags = pcb_no_flags(); + line->ID = pcb_create_ID_get(); + return line; +} + +/* creates a new textobject as part of an element + copies the values to the appropriate text object */ +void pcb_element_text_set(pcb_text_t *Text, pcb_font_t *PCBFont, pcb_coord_t X, pcb_coord_t Y, + unsigned Direction, const char *TextString, int Scale, pcb_flag_t Flags) +{ + free(Text->TextString); + Text->TextString = (TextString && *TextString) ? pcb_strdup(TextString) : NULL; + Text->X = X; + Text->Y = Y; + Text->Direction = Direction; + Text->Flags = Flags; + Text->Scale = Scale; + + /* calculate size of the bounding box */ + pcb_text_bbox(PCBFont, Text); + Text->ID = pcb_create_ID_get(); +} + +/* mirrors the coordinates of an element; an additional offset is passed */ +void pcb_element_mirror(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t yoff) +{ + r_delete_element(Data, Element); + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + line->Point1.X = PCB_SWAP_X(line->Point1.X); + line->Point1.Y = PCB_SWAP_Y(line->Point1.Y) + yoff; + line->Point2.X = PCB_SWAP_X(line->Point2.X); + line->Point2.Y = PCB_SWAP_Y(line->Point2.Y) + yoff; + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + pcb_poly_restore_to_poly(Data, PCB_TYPE_PIN, Element, pin); + pin->X = PCB_SWAP_X(pin->X); + pin->Y = PCB_SWAP_Y(pin->Y) + yoff; + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + pcb_poly_restore_to_poly(Data, PCB_TYPE_PAD, Element, pad); + pad->Point1.X = PCB_SWAP_X(pad->Point1.X); + pad->Point1.Y = PCB_SWAP_Y(pad->Point1.Y) + yoff; + pad->Point2.X = PCB_SWAP_X(pad->Point2.X); + pad->Point2.Y = PCB_SWAP_Y(pad->Point2.Y) + yoff; + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, pad); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + arc->X = PCB_SWAP_X(arc->X); + arc->Y = PCB_SWAP_Y(arc->Y) + yoff; + arc->StartAngle = PCB_SWAP_ANGLE(arc->StartAngle); + arc->Delta = PCB_SWAP_DELTA(arc->Delta); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + text->X = PCB_SWAP_X(text->X); + text->Y = PCB_SWAP_Y(text->Y) + yoff; + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, text); + } + PCB_END_LOOP; + Element->MarkX = PCB_SWAP_X(Element->MarkX); + Element->MarkY = PCB_SWAP_Y(Element->MarkY) + yoff; + + /* now toggle the solder-side flag */ + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, Element); + /* this inserts all of the rtree data too */ + pcb_element_bbox(Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(Data, PCB_TYPE_ELEMENT, Element, Element); +} + +int pcb_element_is_empty(pcb_element_t *Element) +{ + return + (pinlist_length(&Element->Pin) == 0) + && (padlist_length(&Element->Pad) == 0) + && (linelist_length(&Element->Line) == 0) + && (arclist_length(&Element->Arc) == 0); +} + +/* sets the bounding box of an elements */ +void pcb_element_bbox(pcb_data_t *Data, pcb_element_t *Element, pcb_font_t *Font) +{ + pcb_box_t *box, *vbox; + + if (Data && Data->element_tree) + pcb_r_delete_entry(Data->element_tree, (pcb_box_t *) Element); + + if (pcb_element_is_empty(Element)) { + pcb_message(PCB_MSG_ERROR, "Internal error: can not calculate bounding box of empty element. Please report this bug.\n"); + assert(!"empty elem"); + return; + } + + /* first update the text objects */ + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (Data && Data->name_tree[n]) + pcb_r_delete_entry(Data->name_tree[n], (pcb_box_t *) text); + pcb_text_bbox(Font, text); + if (Data && !Data->name_tree[n]) + Data->name_tree[n] = pcb_r_create_tree(NULL, 0, 0); + if (Data) + pcb_r_insert_entry(Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + + /* do not include the elementnames bounding box which + * is handled separately + */ + box = &Element->BoundingBox; + vbox = &Element->VBox; + box->X1 = box->Y1 = PCB_MAX_COORD; + box->X2 = box->Y2 = 0; + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_line_bbox(line); + PCB_MAKE_MIN(box->X1, line->Point1.X - (line->Thickness + 1) / 2); + PCB_MAKE_MIN(box->Y1, line->Point1.Y - (line->Thickness + 1) / 2); + PCB_MAKE_MIN(box->X1, line->Point2.X - (line->Thickness + 1) / 2); + PCB_MAKE_MIN(box->Y1, line->Point2.Y - (line->Thickness + 1) / 2); + PCB_MAKE_MAX(box->X2, line->Point1.X + (line->Thickness + 1) / 2); + PCB_MAKE_MAX(box->Y2, line->Point1.Y + (line->Thickness + 1) / 2); + PCB_MAKE_MAX(box->X2, line->Point2.X + (line->Thickness + 1) / 2); + PCB_MAKE_MAX(box->Y2, line->Point2.Y + (line->Thickness + 1) / 2); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_arc_bbox(arc); + PCB_MAKE_MIN(box->X1, arc->BoundingBox.X1); + PCB_MAKE_MIN(box->Y1, arc->BoundingBox.Y1); + PCB_MAKE_MAX(box->X2, arc->BoundingBox.X2); + PCB_MAKE_MAX(box->Y2, arc->BoundingBox.Y2); + } + PCB_END_LOOP; + *vbox = *box; + PCB_PIN_LOOP(Element); + { + if (Data && Data->pin_tree) + pcb_r_delete_entry(Data->pin_tree, (pcb_box_t *) pin); + pcb_pin_bbox(pin); + if (Data) { + if (!Data->pin_tree) + Data->pin_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Data->pin_tree, (pcb_box_t *) pin, 0); + } + PCB_MAKE_MIN(box->X1, pin->BoundingBox.X1); + PCB_MAKE_MIN(box->Y1, pin->BoundingBox.Y1); + PCB_MAKE_MAX(box->X2, pin->BoundingBox.X2); + PCB_MAKE_MAX(box->Y2, pin->BoundingBox.Y2); + PCB_MAKE_MIN(vbox->X1, pin->X - pin->Thickness / 2); + PCB_MAKE_MIN(vbox->Y1, pin->Y - pin->Thickness / 2); + PCB_MAKE_MAX(vbox->X2, pin->X + pin->Thickness / 2); + PCB_MAKE_MAX(vbox->Y2, pin->Y + pin->Thickness / 2); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + if (Data && Data->pad_tree) + pcb_r_delete_entry(Data->pad_tree, (pcb_box_t *) pad); + pcb_pad_bbox(pad); + if (Data) { + if (!Data->pad_tree) + Data->pad_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Data->pad_tree, (pcb_box_t *) pad, 0); + } + PCB_MAKE_MIN(box->X1, pad->BoundingBox.X1); + PCB_MAKE_MIN(box->Y1, pad->BoundingBox.Y1); + PCB_MAKE_MAX(box->X2, pad->BoundingBox.X2); + PCB_MAKE_MAX(box->Y2, pad->BoundingBox.Y2); + PCB_MAKE_MIN(vbox->X1, MIN(pad->Point1.X, pad->Point2.X) - pad->Thickness / 2); + PCB_MAKE_MIN(vbox->Y1, MIN(pad->Point1.Y, pad->Point2.Y) - pad->Thickness / 2); + PCB_MAKE_MAX(vbox->X2, MAX(pad->Point1.X, pad->Point2.X) + pad->Thickness / 2); + PCB_MAKE_MAX(vbox->Y2, MAX(pad->Point1.Y, pad->Point2.Y) + pad->Thickness / 2); + } + PCB_END_LOOP; + /* now we set the PCB_FLAG_EDGE2 of the pad if Point2 + * is closer to the outside edge than Point1 + */ + PCB_PAD_LOOP(Element); + { + if (pad->Point1.Y == pad->Point2.Y) { + /* horizontal pad */ + if (box->X2 - pad->Point2.X < pad->Point1.X - box->X1) + PCB_FLAG_SET(PCB_FLAG_EDGE2, pad); + else + PCB_FLAG_CLEAR(PCB_FLAG_EDGE2, pad); + } + else { + /* vertical pad */ + if (box->Y2 - pad->Point2.Y < pad->Point1.Y - box->Y1) + PCB_FLAG_SET(PCB_FLAG_EDGE2, pad); + else + PCB_FLAG_CLEAR(PCB_FLAG_EDGE2, pad); + } + } + PCB_END_LOOP; + + /* mark pins with component orientation */ + if ((box->X2 - box->X1) > (box->Y2 - box->Y1)) { + PCB_PIN_LOOP(Element); + { + PCB_FLAG_SET(PCB_FLAG_EDGE2, pin); + } + PCB_END_LOOP; + } + else { + PCB_PIN_LOOP(Element); + { + PCB_FLAG_CLEAR(PCB_FLAG_EDGE2, pin); + } + PCB_END_LOOP; + } + pcb_close_box(box); + pcb_close_box(vbox); + if (Data && !Data->element_tree) + Data->element_tree = pcb_r_create_tree(NULL, 0, 0); + if (Data) + pcb_r_insert_entry(Data->element_tree, box, 0); +} + +static char *BumpName(char *Name) +{ + int num; + char c, *start; + static char temp[256]; + + start = Name; + /* seek end of string */ + while (*Name != 0) + Name++; + /* back up to potential number */ + for (Name--; isdigit((int) *Name); Name--); + Name++; + if (*Name) + num = atoi(Name) + 1; + else + num = 1; + c = *Name; + *Name = 0; + sprintf(temp, "%s%d", start, num); + /* if this is not our string, put back the blown character */ + if (start != temp) + *Name = c; + return (temp); +} + + +/* make a unique name for the name on board + * this can alter the contents of the input string */ +char *pcb_element_uniq_name(pcb_data_t *Data, char *Name) +{ + pcb_bool unique = pcb_true; + /* null strings are ok */ + if (!Name || !*Name) + return (Name); + + for (;;) { + PCB_ELEMENT_LOOP(Data); + { + if (PCB_ELEM_NAME_REFDES(element) && PCB_NSTRCMP(PCB_ELEM_NAME_REFDES(element), Name) == 0) { + Name = BumpName(Name); + unique = pcb_false; + break; + } + } + PCB_END_LOOP; + if (unique) + return (Name); + unique = pcb_true; + } +} + +void r_delete_element(pcb_data_t * data, pcb_element_t * element) +{ + pcb_r_delete_entry(data->element_tree, (pcb_box_t *) element); + PCB_PIN_LOOP(element); + { + pcb_r_delete_entry(data->pin_tree, (pcb_box_t *) pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_r_delete_entry(data->pad_tree, (pcb_box_t *) pad); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_r_delete_entry(data->name_tree[n], (pcb_box_t *) text); + } + PCB_END_LOOP; +} + +/* Returns a best guess about the orientation of an element. The + * value corresponds to the rotation; a difference is the right value + * to pass to RotateElementLowLevel. However, the actual value is no + * indication of absolute rotation; only relative rotation is + * meaningful. + */ +int pcb_element_get_orientation(pcb_element_t * e) +{ + pcb_coord_t pin1x, pin1y, pin2x, pin2y, dx, dy; + pcb_bool found_pin1 = 0; + pcb_bool found_pin2 = 0; + + /* in case we don't find pin 1 or 2, make sure we have initialized these variables */ + pin1x = 0; + pin1y = 0; + pin2x = 0; + pin2y = 0; + + PCB_PIN_LOOP(e); + { + if (PCB_NSTRCMP(pin->Number, "1") == 0) { + pin1x = pin->X; + pin1y = pin->Y; + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pin->Number, "2") == 0) { + pin2x = pin->X; + pin2y = pin->Y; + found_pin2 = 1; + } + } + PCB_END_LOOP; + + PCB_PAD_LOOP(e); + { + if (PCB_NSTRCMP(pad->Number, "1") == 0) { + pin1x = (pad->Point1.X + pad->Point2.X) / 2; + pin1y = (pad->Point1.Y + pad->Point2.Y) / 2; + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pad->Number, "2") == 0) { + pin2x = (pad->Point1.X + pad->Point2.X) / 2; + pin2y = (pad->Point1.Y + pad->Point2.Y) / 2; + found_pin2 = 1; + } + } + PCB_END_LOOP; + + if (found_pin1 && found_pin2) { + dx = pin2x - pin1x; + dy = pin2y - pin1y; + } + else if (found_pin1 && (pin1x || pin1y)) { + dx = pin1x; + dy = pin1y; + } + else if (found_pin2 && (pin2x || pin2y)) { + dx = pin2x; + dy = pin2y; + } + else + return 0; + + if (coord_abs(dx) > coord_abs(dy)) + return dx > 0 ? 0 : 2; + return dy > 0 ? 3 : 1; +} + +/* moves a element by +-X and +-Y */ +void pcb_element_move(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t DX, pcb_coord_t DY) +{ + if (Data) + pcb_r_delete_entry(Data->element_tree, (pcb_box_t *) Element); + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_line_move(line, DX, DY); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + if (Data) { + pcb_r_delete_entry(Data->pin_tree, (pcb_box_t *) pin); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PIN, Element, pin); + } + pcb_pin_move(pin, DX, DY); + if (Data) { + pcb_r_insert_entry(Data->pin_tree, (pcb_box_t *) pin, 0); + pcb_poly_clear_from_poly(Data, PCB_TYPE_PIN, Element, pin); + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + if (Data) { + pcb_r_delete_entry(Data->pad_tree, (pcb_box_t *) pad); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PAD, Element, pad); + } + pcb_pad_move(pad, DX, DY); + if (Data) { + pcb_r_insert_entry(Data->pad_tree, (pcb_box_t *) pad, 0); + pcb_poly_clear_from_poly(Data, PCB_TYPE_PAD, Element, pad); + } + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_arc_move(arc, DX, DY); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (Data && Data->name_tree[n]) + pcb_r_delete_entry(PCB->Data->name_tree[n], (pcb_box_t *) text); + pcb_text_move(text, DX, DY); + if (Data && Data->name_tree[n]) + pcb_r_insert_entry(PCB->Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + PCB_BOX_MOVE_LOWLEVEL(&Element->BoundingBox, DX, DY); + PCB_BOX_MOVE_LOWLEVEL(&Element->VBox, DX, DY); + PCB_MOVE(Element->MarkX, Element->MarkY, DX, DY); + if (Data) + pcb_r_insert_entry(Data->element_tree, (pcb_box_t *) Element, 0); +} + +void *pcb_element_remove(pcb_element_t *Element) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + PCB_CLEAR_PARENT(Element); + + return pcb_elemop_remove(&ctx, Element); +} + +/* rotate an element in 90 degree steps */ +void pcb_element_rotate90(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, unsigned Number) +{ + /* solder side objects need a different orientation */ + + /* the text subroutine decides by itself if the direction + * is to be corrected + */ + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (Data && Data->name_tree[n]) + pcb_r_delete_entry(Data->name_tree[n], (pcb_box_t *) text); + pcb_text_rotate90(text, X, Y, Number); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_line_rotate90(line, X, Y, Number); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + /* pre-delete the pins from the pin-tree before their coordinates change */ + if (Data) + pcb_r_delete_entry(Data->pin_tree, (pcb_box_t *) pin); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PIN, Element, pin); + PCB_PIN_ROTATE90(pin, X, Y, Number); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + /* pre-delete the pads before their coordinates change */ + if (Data) + pcb_r_delete_entry(Data->pad_tree, (pcb_box_t *) pad); + pcb_poly_restore_to_poly(Data, PCB_TYPE_PAD, Element, pad); + PCB_PAD_ROTATE90(pad, X, Y, Number); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_arc_rotate90(arc, X, Y, Number); + } + PCB_END_LOOP; + PCB_COORD_ROTATE90(Element->MarkX, Element->MarkY, X, Y, Number); + /* SetElementBoundingBox reenters the rtree data */ + pcb_element_bbox(Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(Data, PCB_TYPE_ELEMENT, Element, Element); +} + +unsigned int pcb_element_hash(const pcb_element_t *e) +{ + unsigned int val = 0; + gdl_iterator_t it; + + { + pcb_pin_t *p; + pinlist_foreach(&e->Pin, &it, p) { + val ^= pcb_pin_hash(e, p); + } + } + + { + pcb_pad_t *p; + padlist_foreach(&e->Pad, &it, p) { + val ^= pcb_pad_hash(e, p); + } + } + + { + pcb_line_t *l; + linelist_foreach(&e->Line, &it, l) { + val ^= pcb_line_hash(e, l); + } + } + + { + pcb_arc_t *a; + linelist_foreach(&e->Arc, &it, a) { + val ^= pcb_arc_hash(e, a); + } + } + + return val; +} + +int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2) +{ + /* Require the same objects in the same order - bail out at the first mismatch */ + + { + pcb_pin_t *p1, *p2; + p1 = pinlist_first((pinlist_t *)&e1->Pin); + p2 = pinlist_first((pinlist_t *)&e2->Pin); + for(;;) { + if ((p1 == NULL) && (p2 == NULL)) + break; + if (!pcb_pin_eq(e1, p1, e2, p2)) + return 0; + p1 = pinlist_next(p1); + p2 = pinlist_next(p2); + } + } + + { + pcb_pad_t *p1, *p2; + p1 = padlist_first((padlist_t *)&e1->Pad); + p2 = padlist_first((padlist_t *)&e2->Pad); + for(;;) { + if ((p1 == NULL) && (p2 == NULL)) + break; + if (!pcb_pad_eq(e1, p1, e2, p2)) + return 0; + p1 = padlist_next(p1); + p2 = padlist_next(p2); + } + } + + { + pcb_line_t *l1, *l2; + l1 = linelist_first((linelist_t *)&e1->Line); + l2 = linelist_first((linelist_t *)&e2->Line); + for(;;) { + if ((l1 == NULL) && (l2 == NULL)) + break; + if (!pcb_line_eq(e1, l1, e2, l2)) + return 0; + l1 = linelist_next(l1); + l2 = linelist_next(l2); + } + } + + { + pcb_arc_t *a1, *a2; + a1 = arclist_first((arclist_t *)&e1->Arc); + a2 = arclist_first((arclist_t *)&e2->Arc); + for(;;) { + if ((a1 == NULL) && (a2 == NULL)) + break; + if (!pcb_arc_eq(e1, a1, e2, a2)) + return 0; + a1 = arclist_next(a1); + a2 = arclist_next(a2); + } + } + + return 1; +} + + + +/*** ops ***/ +/* copies a element to buffer */ +void *pcb_elemop_add_to_buffer(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_element_t *element; + + element = pcb_element_alloc(ctx->buffer.dst); + pcb_element_copy(ctx->buffer.dst, element, Element, pcb_false, 0, 0); + PCB_FLAG_CLEAR(ctx->buffer.extraflg, element); + if (ctx->buffer.extraflg) { + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + PCB_FLAG_CLEAR(ctx->buffer.extraflg, text); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND | ctx->buffer.extraflg, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND | ctx->buffer.extraflg, pad); + } + PCB_END_LOOP; + } + return (element); +} + +/* moves a element to buffer without allocating memory for pins/names */ +void *pcb_elemop_move_to_buffer(pcb_opctx_t *ctx, pcb_element_t * element) +{ + /* + * Delete the element from the source (remove it from trees, + * restore to polygons) + */ + r_delete_element(ctx->buffer.src, element); + + elementlist_remove(element); + elementlist_append(&ctx->buffer.dst->Element, element); + + PCB_PIN_LOOP(element); + { + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_PIN, element, pin); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_PAD, element, pad); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND, pad); + } + PCB_END_LOOP; + pcb_element_bbox(ctx->buffer.dst, element, pcb_font(PCB, 0, 1)); + /* + * Now clear the from the polygons in the destination + */ + PCB_PIN_LOOP(element); + { + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_PIN, element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_PAD, element, pad); + } + PCB_END_LOOP; + + PCB_SET_PARENT(element, data, ctx->buffer.dst); + + return element; +} + + +/* changes the drilling hole of all pins of an element; returns pcb_true if changed */ +void *pcb_elemop_change_2nd_size(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_bool changed = pcb_false; + pcb_coord_t value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : pin->DrillingHole + ctx->chgsize.value; + if (value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIAHOLE && (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) || value <= pin->Thickness - PCB_MIN_PINORVIACOPPER) + && value != pin->DrillingHole) { + changed = pcb_true; + pcb_undo_add_obj_to_2nd_size(PCB_TYPE_PIN, Element, pin, pin); + pcb_pin_invalidate_erase(pin); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pin->DrillingHole = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, pin, pin); + pin->Thickness = value; + } + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pcb_pin_invalidate_draw(pin); + } + } + PCB_END_LOOP; + if (changed) + return (Element); + else + return (NULL); +} + +/* changes ring dia of all pins of an element; returns pcb_true if changed */ +void *pcb_elemop_change_1st_size(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_bool changed = pcb_false; + pcb_coord_t value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : pin->DrillingHole + ctx->chgsize.value; + if (value <= PCB_MAX_PINORVIASIZE && value >= pin->DrillingHole + PCB_MIN_PINORVIACOPPER && value != pin->Thickness) { + changed = pcb_true; + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, pin, pin); + pcb_pin_invalidate_erase(pin); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pin->Thickness = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, pin, pin); + pin->Thickness = value; + } + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pcb_pin_invalidate_draw(pin); + } + } + PCB_END_LOOP; + if (changed) + return (Element); + else + return (NULL); +} + +/* changes the clearance of all pins of an element; returns pcb_true if changed */ +void *pcb_elemop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_bool changed = pcb_false; + pcb_coord_t value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : pin->Clearance + ctx->chgsize.value; + if (value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIAHOLE && (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) || value <= pin->Thickness - PCB_MIN_PINORVIACOPPER) + && value != pin->Clearance) { + changed = pcb_true; + pcb_undo_add_obj_to_clear_size(PCB_TYPE_PIN, Element, pin, pin); + pcb_pin_invalidate_erase(pin); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pin->Clearance = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, pin, pin); + pin->Thickness = value; + } + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, pin); + pcb_pin_invalidate_draw(pin); + } + } + PCB_END_LOOP; + + PCB_PAD_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : pad->Clearance + ctx->chgsize.value; + if (value <= PCB_MAX_PINORVIASIZE && value >= PCB_MIN_PINORVIAHOLE && value != pad->Clearance) { + changed = pcb_true; + pcb_undo_add_obj_to_clear_size(PCB_TYPE_PAD, Element, pad, pad); + pcb_pad_invalidate_erase(pad); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PAD, Element, pad); + pcb_r_delete_entry(PCB->Data->pad_tree, &pad->BoundingBox); + pad->Clearance = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pad)) { + pcb_undo_add_obj_to_size(PCB_TYPE_PAD, Element, pad, pad); + pad->Thickness = value; + } + /* SetElementBB updates all associated rtrees */ + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PAD, Element, pad); + pcb_pad_invalidate_draw(pad); + } + } + PCB_END_LOOP; + + if (changed) + return (Element); + else + return (NULL); +} + +/* changes the scaling factor of an element's outline; returns pcb_true if changed */ +void *pcb_elemop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_coord_t value; + pcb_bool changed = pcb_false; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + if (pcb_silk_on(PCB)) + pcb_elem_invalidate_erase(Element); + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : line->Thickness + ctx->chgsize.value; + if (value <= PCB_MAX_LINESIZE && value >= PCB_MIN_LINESIZE && value != line->Thickness) { + pcb_undo_add_obj_to_size(PCB_TYPE_ELEMENT_LINE, Element, line, line); + line->Thickness = value; + changed = pcb_true; + } + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : arc->Thickness + ctx->chgsize.value; + if (value <= PCB_MAX_LINESIZE && value >= PCB_MIN_LINESIZE && value != arc->Thickness) { + pcb_undo_add_obj_to_size(PCB_TYPE_ELEMENT_ARC, Element, arc, arc); + arc->Thickness = value; + changed = pcb_true; + } + } + PCB_END_LOOP; + if (pcb_silk_on(PCB)) { + pcb_elem_invalidate_draw(Element); + } + if (changed) + return (Element); + return (NULL); +} + +/* changes the scaling factor of a elementname object; returns pcb_true if changed */ +void *pcb_elemop_change_name_size(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + int value = ctx->chgsize.is_absolute ? PCB_COORD_TO_MIL(ctx->chgsize.value) + : PCB_ELEM_TEXT_DESCRIPTION(Element).Scale + PCB_COORD_TO_MIL(ctx->chgsize.value); + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, &Element->Name[0])) + return (NULL); + if (value <= PCB_MAX_TEXTSCALE && value >= PCB_MIN_TEXTSCALE) { + pcb_elem_name_invalidate_erase(Element); + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + pcb_undo_add_obj_to_size(PCB_TYPE_ELEMENT_NAME, Element, text, text); + pcb_r_delete_entry(PCB->Data->name_tree[n], (pcb_box_t *) text); + text->Scale = value; + pcb_text_bbox(pcb_font(PCB, 0, 1), text); + pcb_r_insert_entry(PCB->Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + pcb_elem_name_invalidate_draw(Element); + return (Element); + } + return (NULL); +} + + +void *pcb_elemop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, &Element->Name[0])) + return (NULL); + if (PCB_ELEMNAME_IDX_VISIBLE() == PCB_ELEMNAME_IDX_REFDES) { + if (conf_core.editor.unique_names && pcb_element_uniq_name(PCB->Data, ctx->chgname.new_name) != ctx->chgname.new_name) { + pcb_message(PCB_MSG_ERROR, _("Error: The name \"%s\" is not unique!\n"), ctx->chgname.new_name); + return ((char *) -1); + } + } + + return pcb_element_text_change(PCB, PCB->Data, Element, PCB_ELEMNAME_IDX_VISIBLE(), ctx->chgname.new_name); +} + +void *pcb_elemop_change_nonetlist(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_FLAG_TOGGLE(PCB_FLAG_NONETLIST, Element); + return Element; +} + + +/* changes the square flag of all pins on an element */ +void *pcb_elemop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *ans = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + ans = pcb_pinop_change_square(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = pcb_padop_change_square(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* sets the square flag of all pins on an element */ +void *pcb_elemop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *ans = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + ans = pcb_pinop_set_square(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = pcb_padop_set_square(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* clears the square flag of all pins on an element */ +void *pcb_elemop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *ans = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + ans = pcb_pinop_clear_square(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = pcb_padop_clear_square(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* changes the octagon flags of all pins of an element */ +void *pcb_elemop_change_octagon(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *result = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + pcb_pinop_change_octagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* sets the octagon flags of all pins of an element */ +void *pcb_elemop_set_octagon(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *result = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + pcb_pinop_set_octagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* clears the octagon flags of all pins of an element */ +void *pcb_elemop_clear_octagon(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + void *result = NULL; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Element)) + return (NULL); + PCB_PIN_LOOP(Element); + { + pcb_pinop_clear_octagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* copies an element onto the PCB. Then does a draw. */ +void *pcb_elemop_copy(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + +#ifdef DEBUG + printf("Entered pcb_elemop_copy, trying to copy element %s\n", Element->Name[1].TextString); +#endif + + pcb_element_t *element = pcb_element_copy(PCB->Data, + NULL, Element, + conf_core.editor.unique_names, ctx->copy.DeltaX, + ctx->copy.DeltaY); + + /* this call clears the polygons */ + pcb_undo_add_obj_to_create(PCB_TYPE_ELEMENT, element, element, element); + if (pcb_silk_on(PCB) && (PCB_FRONT(element) || PCB->InvisibleObjectsOn)) { + pcb_elem_name_invalidate_draw(element); + pcb_elem_package_invalidate_draw(element); + } + if (PCB->PinOn) { + pcb_elem_pp_invalidate_draw(element); + } +#ifdef DEBUG + printf(" ... Leaving pcb_elemop_copy.\n"); +#endif + return (element); +} + +/* moves all names of an element to a new position */ +void *pcb_elemop_move_name(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + if (pcb_silk_on(PCB) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + pcb_elem_name_invalidate_erase(Element); + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (PCB->Data->name_tree[n]) + pcb_r_delete_entry(PCB->Data->name_tree[n], (pcb_box_t *) text); + pcb_text_move(text, ctx->move.dx, ctx->move.dy); + if (PCB->Data->name_tree[n]) + pcb_r_insert_entry(PCB->Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + pcb_elem_name_invalidate_draw(Element); + pcb_draw(); + } + else { + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (PCB->Data->name_tree[n]) + pcb_r_delete_entry(PCB->Data->name_tree[n], (pcb_box_t *) text); + pcb_text_move(text, ctx->move.dx, ctx->move.dy); + if (PCB->Data->name_tree[n]) + pcb_r_insert_entry(PCB->Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + } + return (Element); +} + +/* moves an element */ +void *pcb_elemop_move(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_bool didDraw = pcb_false; + + if (pcb_silk_on(PCB) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + pcb_elem_invalidate_erase(Element); + pcb_element_move(PCB->Data, Element, ctx->move.dx, ctx->move.dy); + pcb_elem_name_invalidate_draw(Element); + pcb_elem_package_invalidate_draw(Element); + didDraw = pcb_true; + } + else { + if (PCB->PinOn) + pcb_elem_pp_invalidate_erase(Element); + pcb_element_move(PCB->Data, Element, ctx->move.dx, ctx->move.dy); + } + if (PCB->PinOn) { + pcb_elem_pp_invalidate_draw(Element); + didDraw = pcb_true; + } + if (didDraw) + pcb_draw(); + return (Element); +} + +/* destroys a element */ +void *pcb_elemop_destroy(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + if (ctx->remove.destroy_target->element_tree) + pcb_r_delete_entry(ctx->remove.destroy_target->element_tree, (pcb_box_t *) Element); + if (ctx->remove.destroy_target->pin_tree) { + PCB_PIN_LOOP(Element); + { + pcb_r_delete_entry(ctx->remove.destroy_target->pin_tree, (pcb_box_t *) pin); + } + PCB_END_LOOP; + } + if (ctx->remove.destroy_target->pad_tree) { + PCB_PAD_LOOP(Element); + { + pcb_r_delete_entry(ctx->remove.destroy_target->pad_tree, (pcb_box_t *) pad); + } + PCB_END_LOOP; + } + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + if (ctx->remove.destroy_target->name_tree[n]) + pcb_r_delete_entry(ctx->remove.destroy_target->name_tree[n], (pcb_box_t *) text); + } + PCB_END_LOOP; + pcb_element_destroy(Element); + + pcb_element_free(Element); + + return NULL; +} + +/* removes an element */ +void *pcb_elemop_remove(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + /* erase from screen */ + if ((pcb_silk_on(PCB) || PCB->PinOn) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + pcb_elem_invalidate_erase(Element); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_ELEMENT, Element, Element, Element); + return NULL; +} + +/* rotates an element */ +void *pcb_elemop_rotate90(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_elem_invalidate_erase(Element); + pcb_element_rotate90(PCB->Data, Element, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + pcb_elem_invalidate_draw(Element); + pcb_draw(); + return (Element); +} + +/* ---------------------------------------------------------------------- + * rotates the name of an element + */ +void *pcb_elemop_rotate90_name(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_elem_name_invalidate_erase(Element); + PCB_ELEMENT_PCB_TEXT_LOOP(Element); + { + pcb_r_delete_entry(PCB->Data->name_tree[n], (pcb_box_t *) text); + pcb_text_rotate90(text, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + pcb_r_insert_entry(PCB->Data->name_tree[n], (pcb_box_t *) text, 0); + } + PCB_END_LOOP; + pcb_elem_name_invalidate_draw(Element); + pcb_draw(); + return (Element); +} + +/*** draw ***/ +void pcb_elem_name_draw(pcb_element_t * element) +{ + if ((conf_core.editor.hide_names && pcb_gui->gui) || PCB_FLAG_TEST(PCB_FLAG_HIDENAME, element)) + return; + if (pcb_draw_doing_pinout || pcb_draw_doing_assy) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element); + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element))) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element_selected); + else if (PCB_FRONT(element)) { +#warning TODO: why do we test for Names flag here instead of elements flag? + if (PCB_FLAG_TEST(PCB_FLAG_NONETLIST, element)) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element_nonetlist); + else + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element); + } + else + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.invisible_objects); + + pcb_text_draw_(&PCB_ELEM_TEXT_VISIBLE(PCB, element), PCB->minSlk, 0); + +} + +pcb_r_dir_t pcb_elem_name_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) b; + pcb_element_t *element = (pcb_element_t *) text->Element; + int *side = cl; + + if (PCB_FLAG_TEST(PCB_FLAG_HIDENAME, element)) + return PCB_R_DIR_NOT_FOUND; + + if (PCB_ON_SIDE(element, *side)) + pcb_elem_name_draw(element); + return PCB_R_DIR_NOT_FOUND; +} + +void pcb_elem_pp_draw(pcb_element_t * element) +{ + PCB_PAD_LOOP(element); + { + if (pcb_draw_doing_pinout || pcb_draw_doing_assy || PCB_FRONT(pad) || PCB->InvisibleObjectsOn) + pcb_pad_draw(pad); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + pcb_pin_draw(pin, pcb_true); + } + PCB_END_LOOP; +} + + +void pcb_elem_package_draw(pcb_element_t * element) +{ + /* set color and draw lines, arcs, text and pins */ + if (pcb_draw_doing_pinout || pcb_draw_doing_assy) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element); + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element_selected); + else if (PCB_FRONT(element)) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element); + else + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.invisible_objects); + + /* draw lines, arcs, text and pins */ + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + pcb_line_draw_(line, 0); + } + PCB_END_LOOP; + PCB_ARC_LOOP(element); + { + pcb_arc_draw_(arc, 0); + } + PCB_END_LOOP; +} + +void pcb_elem_draw(pcb_element_t *element) +{ + pcb_elem_package_draw(element); + pcb_elem_name_draw(element); + pcb_elem_pp_draw(element); +} + +pcb_r_dir_t pcb_elem_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_element_t *element = (pcb_element_t *) b; + int *side = cl; + + if (PCB_ON_SIDE(element, *side)) + pcb_elem_package_draw(element); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static void DrawEMark(pcb_element_t *e, pcb_coord_t X, pcb_coord_t Y, pcb_bool invisible) +{ + pcb_coord_t mark_size = PCB_EMARK_SIZE; + if (!PCB->InvisibleObjectsOn && invisible) + return; + + if (pinlist_length(&e->Pin) != 0) { + pcb_pin_t *pin0 = pinlist_first(&e->Pin); + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin0)) + mark_size = MIN(mark_size, pin0->DrillingHole / 2); + else + mark_size = MIN(mark_size, pin0->Thickness / 2); + } + + if (padlist_length(&e->Pad) != 0) { + pcb_pad_t *pad0 = padlist_first(&e->Pad); + mark_size = MIN(mark_size, pad0->Thickness / 2); + } + + pcb_gui->set_color(pcb_draw_out.fgGC, invisible ? conf_core.appearance.color.invisible_mark : conf_core.appearance.color.element); + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Trace_Cap); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->draw_line(pcb_draw_out.fgGC, X - mark_size, Y, X, Y - mark_size); + pcb_gui->draw_line(pcb_draw_out.fgGC, X + mark_size, Y, X, Y - mark_size); + pcb_gui->draw_line(pcb_draw_out.fgGC, X - mark_size, Y, X, Y + mark_size); + pcb_gui->draw_line(pcb_draw_out.fgGC, X + mark_size, Y, X, Y + mark_size); + + /* + * If an element is locked, place a "L" on top of the "diamond". + * This provides a nice visual indication that it is locked that + * works even for color blind users. + */ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, e)) { + pcb_gui->draw_line(pcb_draw_out.fgGC, X, Y, X + 2 * mark_size, Y); + pcb_gui->draw_line(pcb_draw_out.fgGC, X, Y, X, Y - 4 * mark_size); + } +} + +pcb_r_dir_t pcb_elem_mark_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_element_t *element = (pcb_element_t *) b; + + DrawEMark(element, element->MarkX, element->MarkY, !PCB_FRONT(element)); + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_elem_invalidate_erase(pcb_element_t *Element) +{ + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_line_invalidate_erase(line); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_arc_invalidate_erase(arc); + } + PCB_END_LOOP; + pcb_elem_name_invalidate_erase(Element); + pcb_elem_pp_invalidate_erase(Element); + pcb_flag_erase(&Element->Flags); +} + +void pcb_elem_pp_invalidate_erase(pcb_element_t *Element) +{ + PCB_PIN_LOOP(Element); + { + pcb_pin_invalidate_erase(pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + pcb_pad_invalidate_erase(pad); + } + PCB_END_LOOP; +} + +void pcb_elem_name_invalidate_erase(pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_HIDENAME, Element)) { + return; + } + pcb_text_invalidate_draw(NULL, &PCB_ELEM_TEXT_VISIBLE(PCB, Element)); +} + +void pcb_elem_invalidate_draw(pcb_element_t *Element) +{ + pcb_elem_package_invalidate_draw(Element); + pcb_elem_name_invalidate_draw(Element); + pcb_elem_pp_invalidate_draw(Element); +} + +void pcb_elem_name_invalidate_draw(pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_HIDENAME, Element)) + return; + pcb_text_invalidate_draw(NULL, &PCB_ELEM_TEXT_VISIBLE(PCB, Element)); +} + +void pcb_elem_package_invalidate_draw(pcb_element_t *Element) +{ + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + pcb_line_invalidate_draw(NULL, line); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + pcb_arc_invalidate_draw(NULL, arc); + } + PCB_END_LOOP; +} + +void pcb_elem_pp_invalidate_draw(pcb_element_t *Element) +{ + PCB_PAD_LOOP(Element); + { + if (pcb_draw_doing_pinout || pcb_draw_doing_assy || PCB_FRONT(pad) || PCB->InvisibleObjectsOn) + pcb_pad_invalidate_draw(pad); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + pcb_pin_invalidate_draw(pin); + } + PCB_END_LOOP; +} + +pcb_bool pcb_layer_is_paste_auto_empty(pcb_board_t *pcb, pcb_side_t side) +{ + pcb_bool paste_empty = pcb_true; + PCB_PAD_ALL_LOOP(pcb->Data); + { + if (PCB_ON_SIDE(pad, side) && !PCB_FLAG_TEST(PCB_FLAG_NOPASTE, pad) && pad->Mask > 0) { + paste_empty = pcb_false; + break; + } + } + PCB_ENDALL_LOOP; + return paste_empty; +} Index: tags/1.2.7/src/obj_elem.h =================================================================== --- tags/1.2.7/src/obj_elem.h (nonexistent) +++ tags/1.2.7/src/obj_elem.h (revision 13657) @@ -0,0 +1,171 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: elements */ + +#ifndef PCB_OBJ_ELEM_H +#define PCB_OBJ_ELEM_H + +#include "obj_common.h" +#include "obj_arc_list.h" +#include "obj_line_list.h" +#include "obj_pad_list.h" +#include "obj_pinvia_list.h" +#include "obj_text.h" +#include "font.h" + + +struct pcb_element_s { + PCB_ANYOBJECTFIELDS; + pcb_text_t Name[PCB_MAX_ELEMENTNAMES]; /* the elements names: description text, name on PCB second, value third - see PCB_ELEMNAME_IDX_VISIBLE() below */ + pcb_coord_t MarkX, MarkY; /* position mark */ + pinlist_t Pin; + padlist_t Pad; + linelist_t Line; + arclist_t Arc; + pcb_box_t VBox; + gdl_elem_t link; +}; + +pcb_element_t *pcb_element_alloc(pcb_data_t * data); +void pcb_element_free(pcb_element_t * data); + +pcb_element_t *pcb_element_new(pcb_data_t *Data, pcb_element_t *Element, + pcb_font_t *PCBFont, pcb_flag_t Flags, char *Description, char *NameOnPCB, + char *Value, pcb_coord_t TextX, pcb_coord_t TextY, pcb_uint8_t Direction, + int TextScale, pcb_flag_t TextFlags, pcb_bool uniqueName); + +void pcb_element_destroy(pcb_element_t * element); + +pcb_line_t *pcb_element_line_alloc(pcb_element_t *Element); + + +/* returns non-zero if the element has no objects in it */ +int pcb_element_is_empty(pcb_element_t *Element); + +void pcb_element_bbox(pcb_data_t *Data, pcb_element_t *Element, pcb_font_t *Font); +void pcb_element_rotate90(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_element_rotate(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina, pcb_angle_t angle); + +pcb_bool pcb_element_change_side(pcb_element_t *Element, pcb_coord_t yoff); +pcb_bool pcb_selected_element_change_side(void); +/* Return a relative rotation for an element, useful only for + comparing two similar footprints. */ +int pcb_element_get_orientation(pcb_element_t * e); + +/* hash */ +unsigned int pcb_element_hash(const pcb_element_t *e); +int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2); + + +pcb_bool pcb_element_load_to_buffer(pcb_buffer_t *Buffer, const char *Name); +int pcb_element_load_footprint_by_name(pcb_buffer_t *Buffer, const char *Footprint); +pcb_bool pcb_element_smash_buffer(pcb_buffer_t *Buffer); +pcb_bool pcb_element_convert_from_buffer(pcb_buffer_t *Buffer); +pcb_element_t *pcb_element_copy(pcb_data_t *Data, pcb_element_t *Dest, pcb_element_t *Src, pcb_bool uniqueName, pcb_coord_t dx, pcb_coord_t dy); +char *pcb_element_uniq_name(pcb_data_t *Data, char *Name); + +void r_delete_element(pcb_data_t * data, pcb_element_t * element); + +void pcb_element_move(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t DX, pcb_coord_t DY); +void *pcb_element_remove(pcb_element_t *Element); +void pcb_element_mirror(pcb_data_t *Data, pcb_element_t *Element, pcb_coord_t yoff); + +pcb_arc_t *pcb_element_arc_new(pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, + pcb_coord_t Width, pcb_coord_t Height, pcb_angle_t angle, pcb_angle_t delta, pcb_coord_t Thickness); + +pcb_line_t *pcb_element_line_new(pcb_element_t *Element, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Thickness); + +void pcb_element_text_set(pcb_text_t *Text, pcb_font_t *PCBFont, pcb_coord_t X, pcb_coord_t Y, + unsigned Direction, const char *TextString, int Scale, pcb_flag_t Flags); + + +/* Change the specified text on an element, either on the board (give + PCB, PCB->Data) or in a buffer (give NULL, Buffer->Data). The old + string is returned, and must be properly freed by the caller. */ +char *pcb_element_text_change(pcb_board_t * pcb, pcb_data_t * data, pcb_element_t *Element, int which, char *new_name); + +void pcb_element_text_set_font(pcb_board_t *pcb, pcb_data_t *data, pcb_element_t *Element, int which, pcb_font_id_t fid); +void pcb_element_text_update(pcb_board_t *pcb, pcb_data_t *data, pcb_element_t *Element, int which); + +/* returns whether the silk group of the element's is visible */ +#define pcb_element_silk_vis(elem) \ + (PCB->LayerGroups.grp[((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (elem))) ? pcb_layergrp_get_bottom_silk() : pcb_layergrp_get_top_silk())].vis) + + + +/* --------------------------------------------------------------------------- + * access macros for elements name structure + */ +#define PCB_ELEMNAME_IDX_DESCRIPTION 0 +#define PCB_ELEMNAME_IDX_REFDES 1 +#define PCB_ELEMNAME_IDX_VALUE 2 +#define PCB_ELEMNAME_IDX_VISIBLE() (conf_core.editor.name_on_pcb ? PCB_ELEMNAME_IDX_REFDES :\ + (conf_core.editor.description ? PCB_ELEMNAME_IDX_DESCRIPTION : PCB_ELEMNAME_IDX_VALUE)) + +#define PCB_ELEM_NAME_VISIBLE(p,e) ((e)->Name[PCB_ELEMNAME_IDX_VISIBLE()].TextString) +#define PCB_ELEM_NAME_DESCRIPTION(e) ((e)->Name[PCB_ELEMNAME_IDX_DESCRIPTION].TextString) +#define PCB_ELEM_NAME_REFDES(e) ((e)->Name[PCB_ELEMNAME_IDX_REFDES].TextString) +#define PCB_ELEM_NAME_VALUE(e) ((e)->Name[PCB_ELEMNAME_IDX_VALUE].TextString) + +#define PCB_ELEM_TEXT_VISIBLE(p,e) ((e)->Name[PCB_ELEMNAME_IDX_VISIBLE()]) +#define PCB_ELEM_TEXT_DESCRIPTION(e) ((e)->Name[PCB_ELEMNAME_IDX_DESCRIPTION]) +#define PCB_ELEM_TEXT_REFDES(e) ((e)->Name[PCB_ELEMNAME_IDX_REFDES]) +#define PCB_ELEM_TEXT_VALUE(e) ((e)->Name[PCB_ELEMNAME_IDX_VALUE]) + +/*** loops ***/ + +#define PCB_ELEMENT_LOOP(top) do { \ + pcb_element_t *element; \ + gdl_iterator_t __it__; \ + pinlist_foreach(&(top)->Element, &__it__, element) { + +#define PCB_ELEMENT_PCB_TEXT_LOOP(element) do { \ + pcb_cardinal_t n; \ + pcb_text_t *text; \ + for (n = PCB_MAX_ELEMENTNAMES-1; n != -1; n--) \ + { \ + text = &(element)->Name[n] + +#define PCB_ELEMENT_NAME_LOOP(element) do { \ + pcb_cardinal_t n; \ + char *textstring; \ + for (n = PCB_MAX_ELEMENTNAMES-1; n != -1; n--) \ + { \ + textstring = (element)->Name[n].TextString + +#define PCB_ELEMENT_PCB_LINE_LOOP(element) do { \ + pcb_line_t *line; \ + gdl_iterator_t __it__; \ + linelist_foreach(&(element)->Line, &__it__, line) { + +#define PCB_ELEMENT_ARC_LOOP(element) do { \ + pcb_arc_t *arc; \ + gdl_iterator_t __it__; \ + linelist_foreach(&(element)->Arc, &__it__, arc) { + +#endif + Index: tags/1.2.7/src/obj_elem_draw.h =================================================================== --- tags/1.2.7/src/obj_elem_draw.h (nonexistent) +++ tags/1.2.7/src/obj_elem_draw.h (revision 13657) @@ -0,0 +1,48 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw of elements ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_elem_name_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_elem_mark_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_elem_draw_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_elem_package_draw(pcb_element_t * element); +void pcb_elem_name_draw(pcb_element_t * element); +void pcb_elem_pp_draw(pcb_element_t * element); +void pcb_elem_draw(pcb_element_t *element); + +void pcb_elem_invalidate_erase(pcb_element_t *Element); +void pcb_elem_pp_invalidate_erase(pcb_element_t *Element); +void pcb_elem_name_invalidate_erase(pcb_element_t *Element); + +void pcb_elem_invalidate_draw(pcb_element_t *Element); +void pcb_elem_name_invalidate_draw(pcb_element_t *Element); +void pcb_elem_package_invalidate_draw(pcb_element_t *Element); +void pcb_elem_pp_invalidate_draw(pcb_element_t *Element); Index: tags/1.2.7/src/obj_elem_list.c =================================================================== --- tags/1.2.7/src/obj_elem_list.c (nonexistent) +++ tags/1.2.7/src/obj_elem_list.c (revision 13657) @@ -0,0 +1,32 @@ +/* + * 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. + * + */ + + + +#include "config.h" + +/* include other lists before TDL_DONT_UNDEF makes them pollute the namespace */ +#include "obj_elem.h" + +#define TDL_DONT_UNDEF +#include "obj_elem_list.h" +#include Index: tags/1.2.7/src/obj_elem_list.h =================================================================== --- tags/1.2.7/src/obj_elem_list.h (nonexistent) +++ tags/1.2.7/src/obj_elem_list.h (revision 13657) @@ -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. + * + */ + +#ifndef PCB_OBJ_ELEM_LIST_H +#define PCB_OBJ_ELEM_LIST_H + +#include "obj_elem.h" + +/* List of Elements */ +#define TDL(x) elementlist_ ## x +#define TDL_LIST_T elementlist_t +#define TDL_ITEM_T pcb_element_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define elementlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include "ht_element.h" +#include + +/* Calculate a hash value using the content of the element. The hash value + represents the actual content of an element */ +unsigned int pcb_element_hash(const pcb_element_t *e); + +/* Compare two elements and return 1 if they contain the same objects. */ +int pcb_element_eq(const pcb_element_t *e1, const pcb_element_t *e2); + +/* Create a new local variable to be used for deduplication */ +#define elementlist_dedup_initializer(state) htep_t *state = NULL; + +/* Do a "continue" if an element matching loop_elem has been seen already; + Typically this is invoked as the first statement of an elementlist_foreach() + loop. */ +#define elementlist_dedup_skip(state, loop_elem) \ +switch(1) { \ + case 1: { \ + if (state == NULL) \ + state = htep_alloc(pcb_element_hash, pcb_element_eq); \ + if (htep_has(state, loop_elem)) \ + continue; \ + htep_set(state, loop_elem, 1); \ + } \ +} + +/* use this after the loop to free all memory used by state */ +#define elementlist_dedup_free(state) \ + do { \ + if (state != NULL) { \ + htep_free(state); \ + state = NULL; \ + } \ + } while(0) + + +#ifndef LIST_ELEMENT_NOINSTANT +#include +#include +#endif + +#endif Index: tags/1.2.7/src/obj_elem_op.h =================================================================== --- tags/1.2.7/src/obj_elem_op.h (nonexistent) +++ tags/1.2.7/src/obj_elem_op.h (revision 13657) @@ -0,0 +1,53 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard operations on elements ***/ + +#include "operation.h" + +void *pcb_elemop_add_to_buffer(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_move_to_buffer(pcb_opctx_t *ctx, pcb_element_t * element); +void *pcb_elemop_clear_octagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_set_octagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_octagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_nonetlist(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_name_size(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_1st_size(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_change_2nd_size(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_copy(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_move_name(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_move(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_destroy(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_remove(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_rotate90(pcb_opctx_t *ctx, pcb_element_t *Element); +void *pcb_elemop_rotate90_name(pcb_opctx_t *ctx, pcb_element_t *Element); + Index: tags/1.2.7/src/obj_line.c =================================================================== --- tags/1.2.7/src/obj_line.c (nonexistent) +++ tags/1.2.7/src/obj_line.c (revision 13657) @@ -0,0 +1,1090 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: line segment */ + +#include "config.h" +#include + +#include "undo.h" +#include "board.h" +#include "data.h" +#include "search.h" +#include "polygon.h" +#include "conf_core.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "rotate.h" + +#include "obj_line.h" +#include "obj_line_op.h" + +#include "obj_subc_parent.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_pinvia_draw.h" + + +/**** allocation ****/ + +/* get next slot for a line, allocates memory if necessary */ +pcb_line_t *pcb_line_alloc(pcb_layer_t * layer) +{ + pcb_line_t *new_obj; + + new_obj = calloc(sizeof(pcb_line_t), 1); + new_obj->type = PCB_OBJ_LINE; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, layer, layer); + + linelist_append(&layer->Line, new_obj); + + return new_obj; +} + +void pcb_line_free(pcb_line_t * data) +{ + linelist_remove(data); + free(data); +} + + +/**** 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; + + 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, 0.0, &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, 0.0, &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, 0.0, &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, 0.0, &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_TYPE_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->ID = pcb_create_ID_get(); + Line->Flags = Flags; + PCB_FLAG_CLEAR(PCB_FLAG_RAT, Line); + Line->Thickness = Thickness; + Line->Clearance = Clearance; + 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(); + 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); + if (src->Number != NULL) + dst->Number = pcb_strdup(src->Number); + 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(NULL, 0, 0); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); +} + +/* sets the bounding box of a line */ +void pcb_line_bbox(pcb_line_t *Line) +{ + pcb_coord_t width = (Line->Thickness + Line->Clearance + 1) / 2; + + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + Line->BoundingBox.X1 = MIN(Line->Point1.X, Line->Point2.X) - width; + Line->BoundingBox.X2 = MAX(Line->Point1.X, Line->Point2.X) + width; + Line->BoundingBox.Y1 = MIN(Line->Point1.Y, Line->Point2.Y) - width; + Line->BoundingBox.Y2 = MAX(Line->Point1.Y, Line->Point2.Y) + width; + pcb_close_box(&Line->BoundingBox); + pcb_set_point_bounding_box(&Line->Point1); + pcb_set_point_bounding_box(&Line->Point2); +} + +int pcb_line_eq(const pcb_element_t *e1, const pcb_line_t *l1, const pcb_element_t *e2, const pcb_line_t *l2) +{ + if (pcb_field_neq(l1, l2, Thickness) || pcb_field_neq(l1, l2, Clearance)) return 0; + if (pcb_element_neq_offsx(e1, l1, e2, l2, Point1.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point1.Y)) return 0; + if (pcb_element_neq_offsx(e1, l1, e2, l2, Point2.X) || pcb_element_neq_offsy(e1, l1, e2, l2, Point2.Y)) return 0; + if (pcb_neqs(l1->Number, l2->Number)) return 0; + return 1; +} + + +unsigned int pcb_line_hash(const pcb_element_t *e, const pcb_line_t *l) +{ + return + pcb_hash_coord(l->Thickness) ^ pcb_hash_coord(l->Clearance) ^ + pcb_hash_element_ox(e, l->Point1.X) ^ pcb_hash_element_oy(e, l->Point1.Y) ^ + pcb_hash_element_ox(e, l->Point2.X) ^ pcb_hash_element_oy(e, l->Point2.Y) ^ + pcb_hash_str(l->Number); +} + + +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; + 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); +} + + + +/*** 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 to buffer */ +void *pcb_lineop_move_to_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_line_t * line) +{ + pcb_layer_t *lay = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, layer)]; + + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_LINE, layer, line); + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *) line); + + linelist_remove(line); + linelist_append(&(lay->Line), line); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, line); + + if (!lay->line_tree) + lay->line_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(lay->line_tree, (pcb_box_t *) line, 0); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_LINE, lay, line); + + PCB_SET_PARENT(line, layer, lay); + + 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_TYPE_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_TYPE_LINE, Layer, Line); + Line->Thickness = value; + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_TYPE_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 < ctx->chgsize.pcb->Bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < ctx->chgsize.pcb->Bloat * 2) + value = ctx->chgsize.pcb->Bloat * 2 + 2; + if (value != Line->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_TYPE_LINE, Layer, Line, Line); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_TYPE_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, 0); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_TYPE_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + return (Line); + } + return (NULL); +} + +/* changes the name of a line */ +void *pcb_lineop_change_name(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + char *old = Line->Number; + + Layer = Layer; + Line->Number = ctx->chgname.new_name; + return (old); +} + +/* 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_TYPE_LINE, Layer, Line, Line, pcb_false); + pcb_poly_restore_to_poly(ctx->chgsize.pcb->Data, PCB_TYPE_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_TYPE_LINE, Layer, Line, Line, pcb_true); + pcb_poly_clear_from_poly(ctx->chgsize.pcb->Data, PCB_TYPE_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_TYPE_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); + pcb_draw(); + } + return Line; +} + +void *pcb_lineop_move(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_poly_restore_to_poly(ctx->move.pcb->Data, PCB_TYPE_LINE, Layer, Line); + pcb_lineop_move_noclip(ctx, Layer, Line); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + pcb_poly_clear_from_poly(ctx->move.pcb->Data, PCB_TYPE_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_TYPE_LINE, Layer, Line); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + if (ctx->clip.pcb != NULL) + pcb_poly_clear_from_poly(ctx->clip.pcb->Data, PCB_TYPE_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_TYPE_LINE, Layer, Line); + pcb_r_delete_entry(Layer->line_tree, &Line->BoundingBox); + PCB_MOVE(Point->X, Point->Y, ctx->move.dx, ctx->move.dy); + pcb_line_bbox(Line); + pcb_r_insert_entry(Layer->line_tree, &Line->BoundingBox, 0); + pcb_poly_clear_from_poly(ctx->move.pcb->Data, PCB_TYPE_LINE, Layer, Line); + if (Layer->meta.real.vis) { + pcb_line_invalidate_draw(Layer, Line); + pcb_draw(); + } + 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->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, 0); + if (ctx->move.pcb->RatOn) { + pcb_rat_invalidate_draw((pcb_rat_t *) Line); + pcb_draw(); + } + 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_TYPE_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); + + pcb_draw(); + } + 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); + + linelist_remove(line); + linelist_append(&(Destination->Line), line); + + if (!Destination->line_tree) + Destination->line_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Destination->line_tree, (pcb_box_t *) line, 0); + + PCB_SET_PARENT(line, layer, Destination); + + 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_pin_t *via; + + if ((via = + pcb_via_new(PCB->Data, i->X, i->Y, + conf_core.design.via_thickness, 2 * conf_core.design.clearance, PCB_FLAG_NO, conf_core.design.via_drilling_hole, NULL, pcb_no_flags())) != NULL) { + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + pcb_via_invalidate_draw(via); + } + 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, the object is locked\n")); + return NULL; + } + if (ctx->move.dst_layer == Layer && Layer->meta.real.vis) { + pcb_line_invalidate_draw(Layer, Line); + pcb_draw(); + } + if (ctx->move.dst_layer == Layer) + return (Line); + + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_LINE, Layer, Line, Line); + if (Layer->meta.real.vis) + pcb_line_invalidate_erase(Line); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_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_TYPE_LINE, ctx->move.dst_layer, newone); + if (ctx->move.dst_layer->meta.real.vis) + pcb_line_invalidate_draw(ctx->move.dst_layer, newone); + pcb_draw(); + if (!PCB->ViaOn || 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_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3, + newone->Point1.X, newone->Point1.Y, conf_core.design.via_thickness / 2) == PCB_TYPE_NONE)) { + 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_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3, + newone->Point2.X, newone->Point2.Y, conf_core.design.via_thickness / 2) == PCB_TYPE_NONE)) { + 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); + } + pcb_draw(); + 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); + free(Line->Number); + + 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_TYPE_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); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_LINE, Layer, Line, Line); + return NULL; +} + +void *pcb_line_destroy(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + return pcb_lineop_remove(&ctx, Layer, Line); +} + +/* 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) +{ + 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); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *) line, 0); +} + +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, 0); +} + +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, 0); +} + +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_TYPE_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, 0); + if (!Layer->is_bound) + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + pcb_line_invalidate_draw(Layer, Line); + } + else { + pcb_r_insert_entry(PCB->Data->rat_tree, (pcb_box_t *) Line, 0); + pcb_rat_invalidate_draw((pcb_rat_t *) Line); + } + pcb_draw(); +} + +/* 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_TYPE_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_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_LINE, Layer, line, line); + pcb_line_invalidate_draw(Layer, line); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_LINE, Layer, line); + /* creation call adds it to the rtree */ + } + pcb_draw(); + 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_TYPE_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_TYPE_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_TYPE_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_text_t text; + pcb_term_label_setup(&text, (line->Point1.X + line->Point2.X)/2, (line->Point1.Y + line->Point2.Y)/2, + 100.0, is_line_term_vert(line), pcb_true, line->term, line->intconn); + pcb_draw_invalidate(&text); + } +} + +void pcb_line_draw_label(pcb_line_t *line) +{ + if (line->term != NULL) + pcb_term_label_draw((line->Point1.X + line->Point2.X)/2, (line->Point1.Y + line->Point2.Y)/2, + 100.0, is_line_term_vert(line), pcb_true, line->term, line->intconn); +} + + +void pcb_line_draw_(pcb_line_t *line, int allow_term_gfx) +{ + PCB_DRAW_BBOX(line); + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Trace_Cap); + if (!conf_core.editor.thin_draw && !conf_core.editor.wireframe_draw) { + if ((allow_term_gfx) && pcb_draw_term_need_gfx(line)) { + pcb_gui->set_line_width(pcb_draw_out.active_padGC, line->Thickness); + pcb_gui->draw_line(pcb_draw_out.active_padGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); + pcb_gui->set_line_width(pcb_draw_out.fgGC, PCB_DRAW_TERM_GFX_WIDTH); + } + else + pcb_gui->set_line_width(pcb_draw_out.fgGC, line->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_gui->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_gui->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, line->Thickness, 0); + } + } + + if (line->term != NULL) { + if ((pcb_draw_doing_pinout) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, line)) + pcb_draw_delay_label_add((pcb_any_obj_t *)line); + } +} + +static void pcb_line_draw(pcb_layer_t *layer, pcb_line_t *line, int allow_term_gfx) +{ + const char *color; + char buf[sizeof("#XXXXXX")]; + + 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)) + color = layer->meta.real.selected_color; + 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); + else + color = layer->meta.real.color; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, line)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + + pcb_gui->set_color(pcb_draw_out.fgGC, color); + pcb_line_draw_(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; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(line->parent_type, &line->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_line_draw((pcb_layer_t *)cl, 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; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(line->parent_type, &line->parent)) + return PCB_R_DIR_NOT_FOUND; + + pcb_line_draw((pcb_layer_t *)cl, 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/1.2.7/src/obj_line.h =================================================================== --- tags/1.2.7/src/obj_line.h (nonexistent) +++ tags/1.2.7/src/obj_line.h (revision 13657) @@ -0,0 +1,133 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: line segment */ + +#ifndef PCB_OBJ_LINE_H +#define PCB_OBJ_LINE_H + +#include "obj_common.h" + +struct pcb_line_s { /* holds information about one line */ + PCB_ANYLINEFIELDS; + char *Number; + gdl_elem_t link; /* a line is in a list: either on a layer or in an element */ +}; + +/* 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); +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); + + +/* 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); + +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 */ +int pcb_line_eq(const pcb_element_t *e1, const pcb_line_t *l1, const pcb_element_t *e2, const pcb_line_t *l2); +unsigned int pcb_line_hash(const pcb_element_t *e, const pcb_line_t *l); + + +/*** DRC enforcement (obj_line_drcenf.c) ***/ +void pcb_line_adjust_attached(void); +void pcb_line_adjust_attached_2lines(pcb_bool); +void pcb_line_45(pcb_attached_line_t *); +void pcb_line_enforce_drc(void); + +/* 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((__l__)->Point1.X,(__l__)->Point1.Y,(__dx__),(__dy__)) \ + PCB_MOVE((__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/1.2.7/src/obj_line_draw.h =================================================================== --- tags/1.2.7/src/obj_line_draw.h (nonexistent) +++ tags/1.2.7/src/obj_line_draw.h (revision 13657) @@ -0,0 +1,40 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw of lines ***/ + +/* 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_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_line_t *line); +void pcb_line_name_invalidate_draw(pcb_line_t *line); + Index: tags/1.2.7/src/obj_line_drcenf.c =================================================================== --- tags/1.2.7/src/obj_line_drcenf.c (nonexistent) +++ tags/1.2.7/src/obj_line_drcenf.c (revision 13657) @@ -0,0 +1,539 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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" + +static double drc_lines(pcb_point_t *end, pcb_bool way); + +/* --------------------------------------------------------------------------- + * Adjust the attached line to 45 degrees if necessary + */ +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() ); + +} + +/* --------------------------------------------------------------------------- + * makes the attached line fit into a 45 degree direction + * + * 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; + } +} + +/* --------------------------------------------------------------------------- + * adjusts the insert lines to make them 45 degrees as necessary + */ +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 drcVia_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *via = (pcb_pin_t *) b; + struct drc_info *i = (struct drc_info *) cl; + + if (!PCB_FLAG_TEST(PCB_FLAG_FOUND, via) && pcb_intersect_line_pin(via, i->line)) + longjmp(i->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t drcPad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct drc_info *i = (struct drc_info *) cl; + + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) == i->solder && !PCB_FLAG_TEST(PCB_FLAG_FOUND, pad) && pcb_intersect_line_pad(i->line, pad)) + 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_intersect_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_intersect_line_arc(i->line, arc)) + longjmp(i->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* drc_lines() checks for intersectors against two lines and + * adjusts the end point until there is no intersection or + * it winds up back at the start. If way is pcb_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 + * + * It returns the straight-line length of the best answer, and + * changes the position of the input end point to the best answer. + */ +static double drc_lines(pcb_point_t *end, pcb_bool way) +{ + 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.Flags = line2.Flags = pcb_no_flags(); + line1.Thickness = conf_core.design.line_thickness + 2 * (PCB->Bloat + 1); + line2.Thickness = line1.Thickness; + line1.Clearance = line2.Clearance = 0; + line1.Point1.X = pcb_crosshair.AttachedLine.Point1.X; + line1.Point1.Y = pcb_crosshair.AttachedLine.Point1.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->via_tree, &line1.BoundingBox, NULL, drcVia_callback, &info, NULL); + pcb_r_search(PCB->Data->pin_tree, &line1.BoundingBox, NULL, drcVia_callback, &info, NULL); + if (info.solder || comp == group) + pcb_r_search(PCB->Data->pad_tree, &line1.BoundingBox, NULL, drcPad_callback, &info, NULL); + if (two_lines) { + info.line = &line2; + pcb_r_search(PCB->Data->via_tree, &line2.BoundingBox, NULL, drcVia_callback, &info, NULL); + pcb_r_search(PCB->Data->pin_tree, &line2.BoundingBox, NULL, drcVia_callback, &info, NULL); + if (info.solder || comp == group) + pcb_r_search(PCB->Data->pad_tree, &line2.BoundingBox, NULL, drcPad_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); + } + + end->X = ans.X; + end->Y = ans.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.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->via_tree, &line.BoundingBox, NULL, drcVia_callback, &info, NULL); + pcb_r_search(PCB->Data->pin_tree, &line.BoundingBox, NULL, drcVia_callback, &info, NULL); + if (info.solder || comp == group) + pcb_r_search(PCB->Data->pad_tree, &line.BoundingBox, NULL, drcPad_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; + 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; + + 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 = drc_lines(&rs, pcb_false); + /* then try starting at 45 */ + r2 = drc_lines(&r45, 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/1.2.7/src/obj_line_list.c =================================================================== --- tags/1.2.7/src/obj_line_list.c (nonexistent) +++ tags/1.2.7/src/obj_line_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_line_list.h" +#include Index: tags/1.2.7/src/obj_line_list.h =================================================================== --- tags/1.2.7/src/obj_line_list.h (nonexistent) +++ tags/1.2.7/src/obj_line_list.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_line_op.h =================================================================== --- tags/1.2.7/src/obj_line_op.h (nonexistent) +++ tags/1.2.7/src/obj_line_op.h (revision 13657) @@ -0,0 +1,58 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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_name(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_to_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/1.2.7/src/obj_pad.c =================================================================== --- tags/1.2.7/src/obj_pad.c (nonexistent) +++ tags/1.2.7/src/obj_pad.c (revision 13657) @@ -0,0 +1,629 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: smd pads */ + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "undo.h" +#include "polygon.h" +#include "compat_misc.h" +#include "conf_core.h" + +#include "obj_pad.h" +#include "obj_pad_list.h" +#include "obj_pad_op.h" + + +/* TODO: remove this if draw.[ch] pads are moved */ +#include "draw.h" +#include "obj_text_draw.h" +#include "obj_pad_draw.h" + +#undef max +#define max(x, y) ((x) > (y) ? (x) : (y)) + +/*** allocation ***/ +/* get next slot for a pad, allocates memory if necessary */ +pcb_pad_t *pcb_pad_alloc(pcb_element_t * element) +{ + pcb_pad_t *new_obj; + + new_obj = calloc(sizeof(pcb_pad_t), 1); + new_obj->type = PCB_OBJ_PAD; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, element, element); + + padlist_append(&element->Pad, new_obj); + + return new_obj; +} + +void pcb_pad_free(pcb_pad_t * data) +{ + padlist_remove(data); + free(data); +} + + +/*** utility ***/ +/* creates a new pad in an element */ +pcb_pad_t *pcb_element_pad_new(pcb_element_t *Element, 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_coord_t Mask, const char *Name, const char *Number, pcb_flag_t Flags) +{ + pcb_pad_t *pad = pcb_pad_alloc(Element); + + /* copy values */ + if (X1 > X2 || (X1 == X2 && Y1 > Y2)) { + pad->Point1.X = X2; + pad->Point1.Y = Y2; + pad->Point2.X = X1; + pad->Point2.Y = Y1; + } + else { + pad->Point1.X = X1; + pad->Point1.Y = Y1; + pad->Point2.X = X2; + pad->Point2.Y = Y2; + } + pad->Thickness = Thickness; + pad->Clearance = Clearance; + pad->Mask = Mask; + pad->Name = pcb_strdup_null(Name); + pad->Number = pcb_strdup_null(Number); + pad->Flags = Flags; + PCB_FLAG_CLEAR(PCB_FLAG_WARN, pad); + pad->ID = pcb_create_ID_get(); + pad->Element = Element; + return (pad); +} + +pcb_pad_t *pcb_element_pad_new_rect(pcb_element_t *Element, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Clearance, pcb_coord_t Mask, const char *Name, const char *Number, pcb_flag_t Flags) +{ + pcb_coord_t x1, y1, x2, y2, w, h, t; + pcb_pad_t *pad; + + w = X1 - X2; + h = Y1 - Y2; + t = (w < h) ? w : h; + x1 = X2 + t / 2; + y1 = Y2 + t / 2; + x2 = x1 + (w - t); + y2 = y1 + (h - t); + + pad = pcb_element_pad_new(Element, x1, y1, x2, y2, t, 2 * Clearance, t + Mask, Name, Number, Flags); + PCB_FLAG_SET(PCB_FLAG_SQUARE, pad); + return pad; +} + + +/* sets the bounding box of a pad */ +void pcb_pad_bbox(pcb_pad_t *Pad) +{ + pcb_coord_t width; + pcb_coord_t deltax; + pcb_coord_t deltay; + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + width = (Pad->Thickness + Pad->Clearance + 1) / 2; + width = MAX(width, (Pad->Mask + 1) / 2); + deltax = Pad->Point2.X - Pad->Point1.X; + deltay = Pad->Point2.Y - Pad->Point1.Y; + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad) && deltax != 0 && deltay != 0) { + /* slanted square pad */ + double theta; + pcb_coord_t btx, bty; + + /* T is a vector half a thickness long, in the direction of + one of the corners. */ + theta = atan2(deltay, deltax); + btx = width * cos(theta + M_PI / 4) * sqrt(2.0); + bty = width * sin(theta + M_PI / 4) * sqrt(2.0); + + + Pad->BoundingBox.X1 = MIN(MIN(Pad->Point1.X - btx, Pad->Point1.X - bty), MIN(Pad->Point2.X + btx, Pad->Point2.X + bty)); + Pad->BoundingBox.X2 = MAX(MAX(Pad->Point1.X - btx, Pad->Point1.X - bty), MAX(Pad->Point2.X + btx, Pad->Point2.X + bty)); + Pad->BoundingBox.Y1 = MIN(MIN(Pad->Point1.Y + btx, Pad->Point1.Y - bty), MIN(Pad->Point2.Y - btx, Pad->Point2.Y + bty)); + Pad->BoundingBox.Y2 = MAX(MAX(Pad->Point1.Y + btx, Pad->Point1.Y - bty), MAX(Pad->Point2.Y - btx, Pad->Point2.Y + bty)); + } + else { + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + Pad->BoundingBox.X1 = MIN(Pad->Point1.X, Pad->Point2.X) - width; + Pad->BoundingBox.X2 = MAX(Pad->Point1.X, Pad->Point2.X) + width; + Pad->BoundingBox.Y1 = MIN(Pad->Point1.Y, Pad->Point2.Y) - width; + Pad->BoundingBox.Y2 = MAX(Pad->Point1.Y, Pad->Point2.Y) + width; + } + pcb_close_box(&Pad->BoundingBox); +} + +void pcb_pad_copper_bbox(pcb_box_t *out, pcb_pad_t *Pad) +{ + pcb_coord_t width; + pcb_coord_t deltax; + pcb_coord_t deltay; + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + width = (Pad->Thickness + 1) / 2; + deltax = Pad->Point2.X - Pad->Point1.X; + deltay = Pad->Point2.Y - Pad->Point1.Y; + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad) && deltax != 0 && deltay != 0) { + /* slanted square pad */ + double theta; + pcb_coord_t btx, bty; + + /* T is a vector half a thickness long, in the direction of + one of the corners. */ + theta = atan2(deltay, deltax); + btx = width * cos(theta + M_PI / 4) * sqrt(2.0); + bty = width * sin(theta + M_PI / 4) * sqrt(2.0); + + + out->X1 = MIN(MIN(Pad->Point1.X - btx, Pad->Point1.X - bty), MIN(Pad->Point2.X + btx, Pad->Point2.X + bty)); + out->X2 = MAX(MAX(Pad->Point1.X - btx, Pad->Point1.X - bty), MAX(Pad->Point2.X + btx, Pad->Point2.X + bty)); + out->Y1 = MIN(MIN(Pad->Point1.Y + btx, Pad->Point1.Y - bty), MIN(Pad->Point2.Y - btx, Pad->Point2.Y + bty)); + out->Y2 = MAX(MAX(Pad->Point1.Y + btx, Pad->Point1.Y - bty), MAX(Pad->Point2.Y - btx, Pad->Point2.Y + bty)); + } + else { + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + out->X1 = MIN(Pad->Point1.X, Pad->Point2.X) - width; + out->X2 = MAX(Pad->Point1.X, Pad->Point2.X) + width; + out->Y1 = MIN(Pad->Point1.Y, Pad->Point2.Y) - width; + out->Y2 = MAX(Pad->Point1.Y, Pad->Point2.Y) + width; + } + pcb_close_box(out); +} + +/* changes the nopaste flag of a pad */ +pcb_bool pcb_pad_change_paste(pcb_pad_t *Pad) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad)) + return (pcb_false); + pcb_pad_invalidate_erase(Pad); + pcb_undo_add_obj_to_flag(Pad); + PCB_FLAG_TOGGLE(PCB_FLAG_NOPASTE, Pad); + pcb_pad_invalidate_draw(Pad); + pcb_draw(); + return (pcb_true); +} + +int pcb_pad_eq(const pcb_element_t *e1, const pcb_pad_t *p1, const pcb_element_t *e2, const pcb_pad_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, Point1.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point1.Y)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, Point2.X) || pcb_element_neq_offsy(e1, p1, e2, p2, Point2.Y)) return 0; + if (pcb_field_neq(p1, p2, Mask)) return 0; + if (pcb_neqs(p1->Name, p2->Name)) return 0; + if (pcb_neqs(p1->Number, p2->Number)) return 0; + return 1; +} + +int pcb_pad_eq_padstack(const pcb_pad_t *p1, const pcb_pad_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (PCB_ABS(p1->Point1.X - p1->Point2.X) != PCB_ABS(p2->Point1.X - p2->Point2.X)) return 0; + if (PCB_ABS(p1->Point1.Y - p1->Point2.Y) != PCB_ABS(p2->Point1.Y - p2->Point2.Y)) return 0; + if (pcb_field_neq(p1, p2, Mask)) return 0; + return 1; +} + +unsigned int pcb_pad_hash(const pcb_element_t *e, const pcb_pad_t *p) +{ + return + pcb_hash_coord(p->Thickness) ^ pcb_hash_coord(p->Clearance) ^ + pcb_hash_element_ox(e, p->Point1.X) ^ pcb_hash_element_oy(e, p->Point1.Y) ^ + pcb_hash_element_ox(e, p->Point2.X) ^ pcb_hash_element_oy(e, p->Point2.Y) ^ + pcb_hash_coord(p->Mask) ^ + pcb_hash_str(p->Name) ^ pcb_hash_str(p->Number); +} + +unsigned int pcb_pad_hash_padstack(const pcb_pad_t *p) +{ + return + pcb_hash_coord(p->Thickness) ^ pcb_hash_coord(p->Clearance) ^ + pcb_hash_coord(PCB_ABS(p->Point1.X - p->Point2.X)) ^ + pcb_hash_coord(PCB_ABS(p->Point1.Y - p->Point2.Y)) ^ + pcb_hash_coord(p->Mask); +} + + +/*** ops ***/ + +/* changes the size of a pad */ +void *pcb_padop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pad->Thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad)) + return (NULL); + if (value <= PCB_MAX_PADSIZE && value >= PCB_MIN_PADSIZE && value != Pad->Thickness) { + pcb_undo_add_obj_to_size(PCB_TYPE_PAD, Element, Pad, Pad); + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PAD, Element, Pad, Pad); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_pad_invalidate_erase(Pad); + pcb_r_delete_entry(PCB->Data->pad_tree, &Pad->BoundingBox); + Pad->Mask += value - Pad->Thickness; + Pad->Thickness = value; + /* SetElementBB updates all associated rtrees */ + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_pad_invalidate_draw(Pad); + return (Pad); + } + return (NULL); +} + +/* changes the clearance size of a pad */ +void *pcb_padop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pad->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad)) + return (NULL); + if (value < 0) + value = 0; + else + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < PCB->Bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < PCB->Bloat * 2) + value = PCB->Bloat * 2 + 2; + if (value == Pad->Clearance) + return NULL; + pcb_undo_add_obj_to_clear_size(PCB_TYPE_PAD, Element, Pad, Pad); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_pad_invalidate_erase(Pad); + pcb_r_delete_entry(PCB->Data->pad_tree, &Pad->BoundingBox); + Pad->Clearance = value; + /* SetElementBB updates all associated rtrees */ + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_pad_invalidate_draw(Pad); + return Pad; +} + +/* changes the name of a pad */ +void *pcb_padop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + char *old = Pad->Name; + + Element = Element; /* get rid of 'unused...' warnings */ + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pad)) { + pcb_pad_name_invalidate_erase(Pad); + Pad->Name = ctx->chgname.new_name; + pcb_pad_name_invalidate_draw(Pad); + } + else + Pad->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the number of a pad */ +void *pcb_padop_change_num(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + char *old = Pad->Number; + + Element = Element; /* get rid of 'unused...' warnings */ + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pad)) { + pcb_pad_name_invalidate_erase(Pad); + Pad->Number = ctx->chgname.new_name; + pcb_pad_name_invalidate_draw(Pad); + } + else + Pad->Number = ctx->chgname.new_name; + return (old); +} + +/* changes the square flag of a pad */ +void *pcb_padop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad)) + return (NULL); + pcb_pad_invalidate_erase(Pad); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PAD, Element, Pad, Pad, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_undo_add_obj_to_flag(Pad); + PCB_FLAG_TOGGLE(PCB_FLAG_SQUARE, Pad); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PAD, Element, Pad, Pad, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PAD, Element, Pad); + pcb_pad_invalidate_draw(Pad); + return (Pad); +} + +/* sets the square flag of a pad */ +void *pcb_padop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad) || PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad)) + return (NULL); + + return (pcb_padop_change_square(ctx, Element, Pad)); +} + + +/* clears the square flag of a pad */ +void *pcb_padop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad) || !PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pad)) + return (NULL); + + return (pcb_padop_change_square(ctx, Element, Pad)); +} + +/* changes the mask size of a pad */ +void *pcb_padop_change_mask_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pad->Mask + ctx->chgsize.value; + + value = MAX(value, 0); + if (value == Pad->Mask && ctx->chgsize.value == 0) + value = Pad->Thickness; + if (value != Pad->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PAD, Element, Pad, Pad); + pcb_pad_invalidate_erase(Pad); + pcb_r_delete_entry(PCB->Data->pad_tree, &Pad->BoundingBox); + Pad->Mask = value; + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_pad_invalidate_draw(Pad); + return (Pad); + } + return (NULL); +} + +void *pcb_padop_change_flag(pcb_opctx_t *ctx, pcb_element_t *elem, pcb_pad_t *pad) +{ + static pcb_flag_values_t pcb_pad_flags = 0; + if (pcb_pad_flags == 0) + pcb_pad_flags = pcb_obj_valid_flags(PCB_TYPE_PAD); + + if ((ctx->chgflag.flag & pcb_pad_flags) != ctx->chgflag.flag) + return NULL; + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, pad); + return pad; +} + +/*** draw ***/ +static void draw_pad_name(pcb_pad_t * pad) +{ + pcb_box_t box; + pcb_bool vert, flip_x, flip_y; + pcb_coord_t x_off, y_off; + pcb_text_t text; + char buff[128]; + const char *pn; + + if (!pad->Name || !pad->Name[0]) { + pn = PCB_EMPTY(pad->Number); + } + else { + pn = conf_core.editor.show_number ? pad->Number : pad->Name; + if (pn == NULL) + pn = "n/a"; + } + + if (pad->intconn > 0) + pcb_snprintf(buff, sizeof(buff), "%s[%d]", pn, pad->intconn); + else + strcpy(buff, pn); + text.TextString = buff; + + /* should text be vertical ? */ + vert = (pad->Point1.X == pad->Point2.X); + flip_x = conf_core.editor.view.flip_x; + flip_y = conf_core.editor.view.flip_y; + + if (vert) { + x_off = -pad->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + y_off = pad->Thickness / 2 - conf_core.appearance.pinout.text_offset_x; + box.X1 = pad->Point1.X + (flip_x ? -x_off : x_off); + box.Y1 = flip_y ? (MIN(pad->Point1.Y, pad->Point2.Y) - y_off) : (MAX(pad->Point1.Y, pad->Point2.Y) + y_off); + } + else { + x_off = -pad->Thickness / 2 + conf_core.appearance.pinout.text_offset_x; + y_off = -pad->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + box.X1 = flip_x ? (MAX(pad->Point1.X, pad->Point2.X) - x_off) : (MIN(pad->Point1.X, pad->Point2.X) + x_off); + box.Y1 = pad->Point1.Y + (flip_y ? -y_off : y_off); + } + + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.pin_name); + + text.Flags = (flip_x ^ flip_y) ? pcb_flag_make (PCB_FLAG_ONSOLDER) : pcb_no_flags(); + /* Set font height to approx 90% of pin thickness */ + text.Scale = 90 * pad->Thickness / PCB_FONT_CAPHEIGHT; + text.X = box.X1; + text.Y = box.Y1; + text.fid = 0; + text.Direction = (vert ? 1 : 0) + (flip_x ? 2 : 0); + + pcb_text_draw_(&text, 0, 0); +} + +static void _draw_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + if (clear && !mask && pad->Clearance <= 0) + return; + + PCB_DRAW_BBOX(pad); + + if (conf_core.editor.thin_draw || (clear && conf_core.editor.thin_draw_poly) || conf_core.editor.wireframe_draw) + pcb_gui->thindraw_pcb_pad(gc, pad, clear, mask); + else + pcb_gui->fill_pcb_pad(gc, pad, clear, mask); +} + +void pcb_pad_draw(pcb_pad_t * pad) +{ + const char *color = NULL; + char buf[sizeof("#XXXXXX")]; + + if (pcb_draw_doing_pinout) + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.pin); + else if (PCB_FLAG_TEST(PCB_FLAG_WARN | PCB_FLAG_SELECTED | PCB_FLAG_FOUND, pad)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, pad)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad)) + color = conf_core.appearance.color.pin_selected; + else + color = conf_core.appearance.color.connected; + } + else if (PCB_HAS_COLOROVERRIDE(pad)) { + color = pad->override_color; + } + else if (PCB_FRONT(pad)) + color = conf_core.appearance.color.pin; + else + color = conf_core.appearance.color.invisible_objects; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, pad)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + + if (color != NULL) + pcb_gui->set_color(pcb_draw_out.fgGC, color); + + _draw_pad(pcb_draw_out.fgGC, pad, pcb_false, pcb_false); + + if (pcb_draw_doing_pinout) + draw_pad_name(pad); +} + +pcb_r_dir_t pcb_pad_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + int *side = cl; + + if (PCB_ON_SIDE(pad, *side)) + pcb_pad_draw(pad); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pad_name_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + int *side = cl; + + if (PCB_ON_SIDE(pad, *side)) { + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, pad)) + draw_pad_name(pad); + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pad_clear_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + int *side = cl; + if (PCB_ON_SIDE(pad, *side) && pad->Mask) + _draw_pad(pcb_draw_out.pmGC, pad, pcb_true, pcb_true); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* draws solder paste layer for a given side of the board - only pads get paste */ +void pcb_pad_paste_draw(int side, const pcb_box_t * drawn_area) +{ + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.paste); + PCB_PAD_ALL_LOOP(PCB->Data); + { + if (PCB_ON_SIDE(pad, side) && !PCB_FLAG_TEST(PCB_FLAG_NOPASTE, pad) && pad->Mask > 0) { + pcb_coord_t save_thickness = pad->Thickness; + if (conf_core.design.paste_adjust) + pad->Thickness = max(0, pad->Thickness + conf_core.design.paste_adjust); + if (pad->Mask < pad->Thickness) + _draw_pad(pcb_draw_out.fgGC, pad, pcb_true, pcb_true); + else + _draw_pad(pcb_draw_out.fgGC, pad, pcb_false, pcb_false); + pad->Thickness = save_thickness; + } + } + PCB_ENDALL_LOOP; +} + +static void GatherPadName(pcb_pad_t *Pad) +{ + pcb_box_t box; + pcb_bool vert; + + /* should text be vertical ? */ + vert = (Pad->Point1.X == Pad->Point2.X); + + if (vert) { + box.X1 = Pad->Point1.X - Pad->Thickness / 2; + box.Y1 = MAX(Pad->Point1.Y, Pad->Point2.Y) + Pad->Thickness / 2; + box.X1 += conf_core.appearance.pinout.text_offset_y; + box.Y1 -= conf_core.appearance.pinout.text_offset_x; + box.X2 = box.X1; + box.Y2 = box.Y1; + } + else { + box.X1 = MIN(Pad->Point1.X, Pad->Point2.X) - Pad->Thickness / 2; + box.Y1 = Pad->Point1.Y - Pad->Thickness / 2; + box.X1 += conf_core.appearance.pinout.text_offset_x; + box.Y1 += conf_core.appearance.pinout.text_offset_y; + box.X2 = box.X1; + box.Y2 = box.Y1; + } + + pcb_draw_invalidate(&box); + return; +} + +void pcb_pad_invalidate_erase(pcb_pad_t *Pad) +{ + pcb_draw_invalidate(Pad); + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pad)) + pcb_pad_name_invalidate_erase(Pad); + pcb_flag_erase(&Pad->Flags); +} + +void pcb_pad_name_invalidate_erase(pcb_pad_t *Pad) +{ + GatherPadName(Pad); +} + +void pcb_pad_invalidate_draw(pcb_pad_t *Pad) +{ + pcb_draw_invalidate(Pad); + if (pcb_draw_doing_pinout || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pad)) + pcb_pad_name_invalidate_draw(Pad); +} + +void pcb_pad_name_invalidate_draw(pcb_pad_t *Pad) +{ + GatherPadName(Pad); +} Index: tags/1.2.7/src/obj_pad.h =================================================================== --- tags/1.2.7/src/obj_pad.h (nonexistent) +++ tags/1.2.7/src/obj_pad.h (revision 13657) @@ -0,0 +1,90 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: smd pads */ + +#ifndef PCB_OBJ_PAD_H +#define PCB_OBJ_PAD_H + +#include "obj_common.h" + +struct pcb_pad_s { /* a SMD pad */ + PCB_ANYLINEFIELDS; + pcb_coord_t Mask; + char *Name, *Number; /* 'Line' */ + void *Element; + gdl_elem_t link; /* a pad is in a list (element) */ +}; + + +pcb_pad_t *pcb_pad_alloc(pcb_element_t * element); +void pcb_pad_free(pcb_pad_t * data); + +pcb_pad_t *pcb_element_pad_new(pcb_element_t *Element, 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_coord_t Mask, const char *Name, const char *Number, pcb_flag_t Flags); +pcb_pad_t *pcb_element_pad_new_rect(pcb_element_t *Element, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_coord_t Clearance, pcb_coord_t Mask, const char *Name, const char *Number, pcb_flag_t Flags); + +void pcb_pad_bbox(pcb_pad_t *Pad); + +/* Calculate the net copper bbox and return it in out */ +void pcb_pad_copper_bbox(pcb_box_t *out, pcb_pad_t *Pad); + + +pcb_bool pcb_pad_change_paste(pcb_pad_t *Pad); + +/* hash */ +int pcb_pad_eq(const pcb_element_t *e1, const pcb_pad_t *p1, const pcb_element_t *e2, const pcb_pad_t *p2); +int pcb_pad_eq_padstack(const pcb_pad_t *p1, const pcb_pad_t *p2); +unsigned int pcb_pad_hash(const pcb_element_t *e, const pcb_pad_t *p); +unsigned int pcb_pad_hash_padstack(const pcb_pad_t *p); + + +/* Rather than move the line bounding box, we set it so the point bounding + * boxes are updated too. + */ +#define pcb_pad_move(p,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_pad_t *__p__ = (p); \ + PCB_MOVE((__p__)->Point1.X,(__p__)->Point1.Y,(__dx__),(__dy__)) \ + PCB_MOVE((__p__)->Point2.X,(__p__)->Point2.Y,(__dx__),(__dy__)) \ + pcb_pad_bbox((__p__)); \ + } while(0) + +#define PCB_PAD_ROTATE90(p,x0,y0,n) \ + pcb_line_rotate90(((pcb_line_t *) (p)),(x0),(y0),(n)) + +#define PCB_PAD_LOOP(element) do { \ + pcb_pad_t *pad; \ + gdl_iterator_t __it__; \ + padlist_foreach(&(element)->Pad, &__it__, pad) { + +#define PCB_PAD_ALL_LOOP(top) \ + PCB_ELEMENT_LOOP(top); \ + PCB_PAD_LOOP(element) + + +#endif + Index: tags/1.2.7/src/obj_pad_draw.h =================================================================== --- tags/1.2.7/src/obj_pad_draw.h (nonexistent) +++ tags/1.2.7/src/obj_pad_draw.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw on pads ***/ + + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_pad_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_pad_name_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_pad_clear_callback(const pcb_box_t * b, void *cl); +#endif + +void pcb_pad_draw(pcb_pad_t * pad); +void pcb_pad_paste_draw(int side, const pcb_box_t * drawn_area); +void pcb_pad_invalidate_erase(pcb_pad_t *Pad); +void pcb_pad_name_invalidate_erase(pcb_pad_t *Pad); +void pcb_pad_invalidate_draw(pcb_pad_t *Pad); +void pcb_pad_name_invalidate_draw(pcb_pad_t *Pad); Index: tags/1.2.7/src/obj_pad_list.c =================================================================== --- tags/1.2.7/src/obj_pad_list.c (nonexistent) +++ tags/1.2.7/src/obj_pad_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_pad_list.h" +#include Index: tags/1.2.7/src/obj_pad_list.h =================================================================== --- tags/1.2.7/src/obj_pad_list.h (nonexistent) +++ tags/1.2.7/src/obj_pad_list.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * 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. + * + */ + +#ifndef PCB_OBJ_PAD_LIST_H +#define PCB_OBJ_PAD_LIST_H + +#include "obj_pad.h" + +/* List of Pads */ +#define TDL(x) padlist_ ## x +#define TDL_LIST_T padlist_t +#define TDL_ITEM_T pcb_pad_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define padlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + + +#include +#include + +#endif Index: tags/1.2.7/src/obj_pad_op.h =================================================================== --- tags/1.2.7/src/obj_pad_op.h (nonexistent) +++ tags/1.2.7/src/obj_pad_op.h (revision 13657) @@ -0,0 +1,44 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard operations on pads ***/ + +#include "operation.h" + +void *pcb_padop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_num(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_mask_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *pcb_padop_change_flag(pcb_opctx_t *ctx, pcb_element_t *elem, pcb_pad_t *pad); + + + + + Index: tags/1.2.7/src/obj_pinvia.c =================================================================== --- tags/1.2.7/src/obj_pinvia.c (nonexistent) +++ tags/1.2.7/src/obj_pinvia.c (revision 13657) @@ -0,0 +1,1249 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: pins and vias */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "undo.h" +#include "conf_core.h" +#include "polygon.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "stub_vendor.h" +#include "rotate.h" + +#include "obj_pinvia.h" +#include "obj_pinvia_op.h" +#include "obj_subc_parent.h" + +/* TODO: consider removing this by moving pin/via functions here: */ +#include "draw.h" +#include "obj_text_draw.h" +#include "obj_pinvia_draw.h" + +/*** allocation ***/ + +/* get next slot for a via, allocates memory if necessary */ +pcb_pin_t *pcb_via_alloc(pcb_data_t * data) +{ + pcb_pin_t *new_obj; + + new_obj = calloc(sizeof(pcb_pin_t), 1); + new_obj->type = PCB_OBJ_VIA; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, data, data); + + pinlist_append(&data->Via, new_obj); + + return new_obj; +} + +void pcb_via_free(pcb_pin_t * data) +{ + pinlist_remove(data); + free(data); +} + +/* get next slot for a pin, allocates memory if necessary */ +pcb_pin_t *pcb_pin_alloc(pcb_element_t * element) +{ + pcb_pin_t *new_obj; + + new_obj = calloc(sizeof(pcb_pin_t), 1); + new_obj->type = PCB_OBJ_PIN; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, element, element); + + pinlist_append(&element->Pin, new_obj); + + return new_obj; +} + +void pcb_pin_free(pcb_pin_t * data) +{ + pinlist_remove(data); + free(data); +} + + + +/*** utility ***/ + +/* creates a new via */ +pcb_pin_t *pcb_via_new(pcb_data_t *Data, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_coord_t Mask, pcb_coord_t DrillingHole, const char *Name, pcb_flag_t Flags) +{ + pcb_pin_t *Via; + + if (!pcb_create_being_lenient) { + PCB_VIA_LOOP(Data); + { + if (pcb_distance(X, Y, via->X, via->Y) <= via->DrillingHole / 2 + DrillingHole / 2) { + pcb_message(PCB_MSG_WARNING, _("%m+Dropping via at %$mD because it's hole would overlap with the via " + "at %$mD\n"), conf_core.editor.grid_unit->allow, X, Y, via->X, via->Y); + return (NULL); /* don't allow via stacking */ + } + } + PCB_END_LOOP; + } + + Via = pcb_via_alloc(Data); + + if (!Via) + return (Via); + /* copy values */ + Via->X = X; + Via->Y = Y; + Via->Thickness = Thickness; + Via->Clearance = Clearance; + Via->Mask = Mask; + Via->DrillingHole = pcb_stub_vendor_drill_map(DrillingHole); + if (Via->DrillingHole != DrillingHole) { + pcb_message(PCB_MSG_INFO, _("%m+Mapped via drill hole to %$mS from %$mS per vendor table\n"), + conf_core.editor.grid_unit->allow, Via->DrillingHole, DrillingHole); + } + + Via->Name = pcb_strdup_null(Name); + Via->Flags = Flags; + PCB_FLAG_CLEAR(PCB_FLAG_WARN, Via); + PCB_FLAG_SET(PCB_FLAG_VIA, Via); + Via->ID = pcb_create_ID_get(); + + /* + * don't complain about PCB_MIN_PINORVIACOPPER on a mounting hole (pure + * hole) + */ + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, Via) && (Via->Thickness < Via->DrillingHole + PCB_MIN_PINORVIACOPPER)) { + Via->Thickness = Via->DrillingHole + PCB_MIN_PINORVIACOPPER; + pcb_message(PCB_MSG_WARNING, _("%m+Increased via thickness to %$mS to allow enough copper" + " at %$mD.\n"), conf_core.editor.grid_unit->allow, Via->Thickness, Via->X, Via->Y); + } + + pcb_add_via(Data, Via); + return (Via); +} + +static pcb_pin_t *pcb_via_copy_meta(pcb_pin_t *dst, pcb_pin_t *src) +{ + if (dst == NULL) + return NULL; + pcb_attribute_copy_all(&dst->Attributes, &src->Attributes); + if (src->Number != NULL) + dst->Number = pcb_strdup(src->Number); + if (src->Name != NULL) + dst->Name = pcb_strdup(src->Name); + return dst; +} + +pcb_pin_t *pcb_via_dup(pcb_data_t *data, pcb_pin_t *src) +{ + pcb_pin_t *p = pcb_via_new(data, src->X, src->Y, src->Thickness, src->Clearance, src->Mask, src->DrillingHole, src->Name, src->Flags); + return pcb_via_copy_meta(p, src); +} + +pcb_pin_t *pcb_via_dup_at(pcb_data_t *data, pcb_pin_t *src, pcb_coord_t dx, pcb_coord_t dy) +{ + pcb_pin_t *p = pcb_via_new(data, src->X+dx, src->Y+dy, src->Thickness, src->Clearance, src->Mask, src->DrillingHole, src->Name, src->Flags); + return pcb_via_copy_meta(p, src); +} + +/* creates a new pin in an element */ +pcb_pin_t *pcb_element_pin_new(pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_coord_t Mask, pcb_coord_t DrillingHole, const char *Name, const char *Number, pcb_flag_t Flags) +{ + pcb_pin_t *pin = pcb_pin_alloc(Element); + + /* copy values */ + pin->X = X; + pin->Y = Y; + pin->Thickness = Thickness; + pin->Clearance = Clearance; + pin->Mask = Mask; + pin->Name = pcb_strdup_null(Name); + pin->Number = pcb_strdup_null(Number); + pin->Flags = Flags; + PCB_FLAG_CLEAR(PCB_FLAG_WARN, pin); + PCB_FLAG_SET(PCB_FLAG_PIN, pin); + pin->ID = pcb_create_ID_get(); + pin->Element = Element; + + /* + * If there is no vendor drill map installed, this will simply + * return DrillingHole. + */ + pin->DrillingHole = pcb_stub_vendor_drill_map(DrillingHole); + + /* Unless we should not map drills on this element, map them! */ + if (pcb_stub_vendor_is_element_mappable(Element)) { + if (pin->DrillingHole < PCB_MIN_PINORVIASIZE) { + pcb_message(PCB_MSG_WARNING, _("%m+Did not map pin #%s (%s) drill hole because %$mS is below the minimum allowed size\n"), + conf_core.editor.grid_unit->allow, PCB_UNKNOWN(Number), PCB_UNKNOWN(Name), pin->DrillingHole); + pin->DrillingHole = DrillingHole; + } + else if (pin->DrillingHole > PCB_MAX_PINORVIASIZE) { + pcb_message(PCB_MSG_WARNING, _("%m+Did not map pin #%s (%s) drill hole because %$mS is above the maximum allowed size\n"), + conf_core.editor.grid_unit->allow, PCB_UNKNOWN(Number), PCB_UNKNOWN(Name), pin->DrillingHole); + pin->DrillingHole = DrillingHole; + } + else if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) + && (pin->DrillingHole > pin->Thickness - PCB_MIN_PINORVIACOPPER)) { + pcb_message(PCB_MSG_WARNING, _("%m+Did not map pin #%s (%s) drill hole because %$mS does not leave enough copper\n"), + conf_core.editor.grid_unit->allow, PCB_UNKNOWN(Number), PCB_UNKNOWN(Name), pin->DrillingHole); + pin->DrillingHole = DrillingHole; + } + } + else { + pin->DrillingHole = DrillingHole; + } + + if (pin->DrillingHole != DrillingHole) { + pcb_message(PCB_MSG_INFO, _("%m+Mapped pin drill hole to %$mS from %$mS per vendor table\n"), + conf_core.editor.grid_unit->allow, pin->DrillingHole, DrillingHole); + } + + return (pin); +} + + + +void pcb_add_via(pcb_data_t *Data, pcb_pin_t *Via) +{ + pcb_pin_bbox(Via); + if (!Data->via_tree) + Data->via_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Data->via_tree, (pcb_box_t *) Via, 0); + PCB_SET_PARENT(Via, data, Data); +} + +/* sets the bounding box of a pin or via */ +void pcb_pin_bbox(pcb_pin_t *Pin) +{ + pcb_coord_t width; + + if ((PCB_FLAG_SQUARE_GET(Pin) > 1) && (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pin))) { + pcb_polyarea_t *p = pcb_poly_from_pin(Pin, PIN_SIZE(Pin), Pin->Clearance); + pcb_polyarea_bbox(p, &Pin->BoundingBox); + pcb_polyarea_free(&p); + } + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + width = MAX(Pin->Clearance + PIN_SIZE(Pin), Pin->Mask) / 2; + + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + Pin->BoundingBox.X1 = Pin->X - width; + Pin->BoundingBox.Y1 = Pin->Y - width; + Pin->BoundingBox.X2 = Pin->X + width; + Pin->BoundingBox.Y2 = Pin->Y + width; + pcb_close_box(&Pin->BoundingBox); +} + +void pcb_pin_copper_bbox(pcb_box_t *out, pcb_pin_t *Pin) +{ + pcb_coord_t width; + + if ((PCB_FLAG_SQUARE_GET(Pin) > 1) && (PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pin))) { + pcb_polyarea_t *p = pcb_poly_from_pin(Pin, PIN_SIZE(Pin), 0); + pcb_polyarea_bbox(p, out); + pcb_polyarea_free(&p); + return; + } + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + width = PIN_SIZE(Pin) / 2; + + /* Adjust for our discrete polygon approximation */ + width = (double) width *PCB_POLY_CIRC_RADIUS_ADJ + 0.5; + + out->X1 = Pin->X - width; + out->Y1 = Pin->Y - width; + out->X2 = Pin->X + width; + out->Y2 = Pin->Y + width; + pcb_close_box(out); +} + +void pcb_via_rotate(pcb_data_t *Data, pcb_pin_t *Via, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina) +{ + pcb_r_delete_entry(Data->via_tree, (pcb_box_t *) Via); + pcb_rotate(&Via->X, &Via->Y, X, Y, cosa, sina); + pcb_pin_bbox(Via); + pcb_r_insert_entry(Data->via_tree, (pcb_box_t *) Via, 0); +} + +void pcb_via_mirror(pcb_data_t *Data, pcb_pin_t *via, pcb_coord_t y_offs) +{ + if (Data->via_tree != NULL) + pcb_r_delete_entry(Data->via_tree, (pcb_box_t *) via); + via->X = PCB_SWAP_X(via->X); + via->Y = PCB_SWAP_Y(via->Y) + y_offs; + pcb_pin_bbox(via); + if (Data->via_tree != NULL) + pcb_r_insert_entry(Data->via_tree, (pcb_box_t *) via, 0); +} + +void pcb_via_flip_side(pcb_data_t *Data, pcb_pin_t *via) +{ + pcb_r_delete_entry(Data->via_tree, (pcb_box_t *) via); + via->X = PCB_SWAP_X(via->X); + via->Y = PCB_SWAP_Y(via->Y); + pcb_pin_bbox(via); + pcb_r_insert_entry(Data->via_tree, (pcb_box_t *) via, 0); +} + +int pcb_pin_eq(const pcb_element_t *e1, const pcb_pin_t *p1, const pcb_element_t *e2, const pcb_pin_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_field_neq(p1, p2, Mask) || pcb_field_neq(p1, p2, DrillingHole)) return 0; + if (pcb_element_neq_offsx(e1, p1, e2, p2, X) || pcb_element_neq_offsy(e1, p1, e2, p2, Y)) return 0; + if (pcb_neqs(p1->Name, p2->Name)) return 0; + if (pcb_neqs(p1->Number, p2->Number)) return 0; + return 1; +} + +int pcb_pin_eq_padstack(const pcb_pin_t *p1, const pcb_pin_t *p2) +{ + if (pcb_field_neq(p1, p2, Thickness) || pcb_field_neq(p1, p2, Clearance)) return 0; + if (pcb_field_neq(p1, p2, Mask) || pcb_field_neq(p1, p2, DrillingHole)) return 0; + return 1; +} + +unsigned int pcb_pin_hash(const pcb_element_t *e, const pcb_pin_t *p) +{ + return + pcb_hash_coord(p->Thickness) ^ pcb_hash_coord(p->Clearance) ^ + pcb_hash_coord(p->Mask) ^ pcb_hash_coord(p->DrillingHole) ^ + pcb_hash_element_ox(e, p->X) ^ pcb_hash_element_oy(e, p->Y) ^ + pcb_hash_str(p->Name) ^ pcb_hash_str(p->Number); +} + +unsigned int pcb_pin_hash_padstack(const pcb_pin_t *p) +{ + return + pcb_hash_coord(p->Thickness) ^ pcb_hash_coord(p->Clearance) ^ + pcb_hash_coord(p->Mask) ^ pcb_hash_coord(p->DrillingHole); +} + +/*** ops ***/ +/* copies a via to paste buffer */ +void *pcb_viaop_add_to_buffer(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_pin_t *v = pcb_via_new(ctx->buffer.dst, Via->X, Via->Y, Via->Thickness, Via->Clearance, Via->Mask, Via->DrillingHole, Via->Name, pcb_flag_mask(Via->Flags, PCB_FLAG_FOUND | ctx->buffer.extraflg)); + return pcb_via_copy_meta(v, Via); +} + +/* moves a via to paste buffer without allocating memory for the name */ +void *pcb_viaop_move_to_buffer(pcb_opctx_t *ctx, pcb_pin_t * via) +{ + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_VIA, via, via); + + pcb_r_delete_entry(ctx->buffer.src->via_tree, (pcb_box_t *) via); + pinlist_remove(via); + pinlist_append(&ctx->buffer.dst->Via, via); + + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND, via); + + if (!ctx->buffer.dst->via_tree) + ctx->buffer.dst->via_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(ctx->buffer.dst->via_tree, (pcb_box_t *) via, 0); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_VIA, via, via); + PCB_SET_PARENT(via, data, ctx->buffer.dst); + return via; +} + +/* changes the thermal on a via */ +void *pcb_viaop_change_thermal(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, Via, Via, Via, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, CURRENT, Via); + pcb_undo_add_obj_to_flag(Via); + if (!ctx->chgtherm.style) /* remove the thermals */ + PCB_FLAG_THERM_CLEAR(INDEXOFCURRENT, Via); + else + PCB_FLAG_THERM_ASSIGN(INDEXOFCURRENT, ctx->chgtherm.style, Via); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, Via, Via, Via, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, CURRENT, Via); + pcb_via_invalidate_draw(Via); + return Via; +} + +/* changes the thermal on a pin */ +void *pcb_pinop_change_thermal(pcb_opctx_t *ctx, pcb_element_t *element, pcb_pin_t *Pin) +{ + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, element, Pin, Pin, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, CURRENT, Pin); + pcb_undo_add_obj_to_flag(Pin); + if (!ctx->chgtherm.style) /* remove the thermals */ + PCB_FLAG_THERM_CLEAR(INDEXOFCURRENT, Pin); + else + PCB_FLAG_THERM_ASSIGN(INDEXOFCURRENT, ctx->chgtherm.style, Pin); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, element, Pin, Pin, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, CURRENT, Pin); + pcb_pin_invalidate_draw(Pin); + return Pin; +} + +/* changes the size of a via */ +void *pcb_viaop_change_size(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = ctx->chgsize.is_absolute ? ctx->chgsize.value : Via->Thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, Via) && value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIASIZE && value >= Via->DrillingHole + PCB_MIN_PINORVIACOPPER && value != Via->Thickness) { + pcb_undo_add_obj_to_size(PCB_TYPE_VIA, Via, Via, Via); + pcb_via_invalidate_erase(Via); + pcb_r_delete_entry(PCB->Data->via_tree, (pcb_box_t *) Via); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Via, Via); + if (Via->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_VIA, Via, Via, Via); + Via->Mask += value - Via->Thickness; + } + Via->Thickness = value; + pcb_pin_bbox(Via); + pcb_r_insert_entry(PCB->Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_via_invalidate_draw(Via); + return (Via); + } + return (NULL); +} + +/* changes the drilling hole of a via */ +void *pcb_viaop_change_2nd_size(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Via->DrillingHole + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + if (value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIAHOLE && (PCB_FLAG_TEST(PCB_FLAG_HOLE, Via) || value <= Via->Thickness - PCB_MIN_PINORVIACOPPER) + && value != Via->DrillingHole) { + pcb_undo_add_obj_to_2nd_size(PCB_TYPE_VIA, Via, Via, Via); + pcb_via_invalidate_erase(Via); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + Via->DrillingHole = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, Via)) { + pcb_undo_add_obj_to_size(PCB_TYPE_VIA, Via, Via, Via); + Via->Thickness = value; + } + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_via_invalidate_draw(Via); + return (Via); + } + return (NULL); +} + +/* changes the drilling hole of a pin */ +void *pcb_pinop_change_2nd_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pin->DrillingHole + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + if (value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIAHOLE && (PCB_FLAG_TEST(PCB_FLAG_HOLE, Pin) || value <= Pin->Thickness - PCB_MIN_PINORVIACOPPER) + && value != Pin->DrillingHole) { + pcb_undo_add_obj_to_2nd_size(PCB_TYPE_PIN, Element, Pin, Pin); + pcb_pin_invalidate_erase(Pin); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + Pin->DrillingHole = value; + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, Pin)) { + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, Pin, Pin); + Pin->Thickness = value; + } + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_pin_invalidate_draw(Pin); + return (Pin); + } + return (NULL); +} + + +/* changes the clearance size of a via */ +void *pcb_viaop_change_clear_size(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Via->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < PCB->Bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < PCB->Bloat * 2) + value = PCB->Bloat * 2 + 2; + if (Via->Clearance == value) + return NULL; + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_undo_add_obj_to_clear_size(PCB_TYPE_VIA, Via, Via, Via); + pcb_via_invalidate_erase(Via); + pcb_r_delete_entry(PCB->Data->via_tree, (pcb_box_t *) Via); + Via->Clearance = value; + pcb_pin_bbox(Via); + pcb_r_insert_entry(PCB->Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_via_invalidate_draw(Via); + Via->Element = NULL; + return (Via); +} + + +/* changes the size of a pin */ +void *pcb_pinop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pin->Thickness + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, Pin) && value <= PCB_MAX_PINORVIASIZE && + value >= PCB_MIN_PINORVIASIZE && value >= Pin->DrillingHole + PCB_MIN_PINORVIACOPPER && value != Pin->Thickness) { + pcb_undo_add_obj_to_size(PCB_TYPE_PIN, Element, Pin, Pin); + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PIN, Element, Pin, Pin); + pcb_pin_invalidate_erase(Pin); + pcb_r_delete_entry(PCB->Data->pin_tree, &Pin->BoundingBox); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + Pin->Mask += value - Pin->Thickness; + Pin->Thickness = value; + /* SetElementBB updates all associated rtrees */ + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_pin_invalidate_draw(Pin); + return (Pin); + } + return (NULL); +} + +/* changes the clearance size of a pin */ +void *pcb_pinop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pin->Clearance + ctx->chgsize.value; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (!ctx->chgsize.is_absolute && ctx->chgsize.value < 0 && value < PCB->Bloat * 2) + value = 0; + if (ctx->chgsize.value > 0 && value < PCB->Bloat * 2) + value = PCB->Bloat * 2 + 2; + if (Pin->Clearance == value) + return NULL; + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_undo_add_obj_to_clear_size(PCB_TYPE_PIN, Element, Pin, Pin); + pcb_pin_invalidate_erase(Pin); + pcb_r_delete_entry(PCB->Data->pin_tree, &Pin->BoundingBox); + Pin->Clearance = value; + /* SetElementBB updates all associated rtrees */ + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_pin_invalidate_draw(Pin); + return (Pin); +} + +/* changes the name of a via */ +void *pcb_viaop_change_name(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + char *old = Via->Name; + + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Via)) { + pcb_pin_name_invalidate_erase(Via); + Via->Name = ctx->chgname.new_name; + pcb_pin_name_invalidate_draw(Via); + } + else + Via->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the name of a pin */ +void *pcb_pinop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + char *old = Pin->Name; + + Element = Element; /* get rid of 'unused...' warnings */ + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pin)) { + pcb_pin_name_invalidate_erase(Pin); + Pin->Name = ctx->chgname.new_name; + pcb_pin_name_invalidate_draw(Pin); + } + else + Pin->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the number of a pin */ +void *pcb_pinop_change_num(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + char *old = Pin->Number; + + Element = Element; /* get rid of 'unused...' warnings */ + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pin)) { + pcb_pin_name_invalidate_erase(Pin); + Pin->Number = ctx->chgname.new_name; + pcb_pin_name_invalidate_draw(Pin); + } + else + Pin->Number = ctx->chgname.new_name; + return (old); +} + + +/* changes the square flag of a via */ +void *pcb_viaop_change_square(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + pcb_via_invalidate_erase(Via); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, NULL, Via, Via, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, NULL, Via); + pcb_undo_add_obj_to_flag(Via); + PCB_FLAG_SQUARE_ASSIGN(ctx->chgsize.value, Via); + if (ctx->chgsize.value == 0) + PCB_FLAG_CLEAR(PCB_FLAG_SQUARE, Via); + else + PCB_FLAG_SET(PCB_FLAG_SQUARE, Via); + pcb_pin_bbox(Via); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, NULL, Via, Via, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, NULL, Via); + pcb_via_invalidate_draw(Via); + return (Via); +} + +/* changes the square flag of a pin */ +void *pcb_pinop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + pcb_pin_invalidate_erase(Pin); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, Element, Pin, Pin, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_undo_add_obj_to_flag(Pin); + PCB_FLAG_SQUARE_ASSIGN(ctx->chgsize.value, Pin); + if (ctx->chgsize.value == 0) + PCB_FLAG_CLEAR(PCB_FLAG_SQUARE, Pin); + else + PCB_FLAG_SET(PCB_FLAG_SQUARE, Pin); + pcb_pin_bbox(Pin); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, Element, Pin, Pin, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_pin_invalidate_draw(Pin); + return (Pin); +} + +/* sets the square flag of a pin */ +void *pcb_pinop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin) || PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pin)) + return (NULL); + + return (pcb_pinop_change_square(ctx, Element, Pin)); +} + +/* clears the square flag of a pin */ +void *pcb_pinop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin) || !PCB_FLAG_TEST(PCB_FLAG_SQUARE, Pin)) + return (NULL); + + return (pcb_pinop_change_square(ctx, Element, Pin)); +} + +/* changes the octagon flag of a via */ +void *pcb_viaop_change_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + pcb_via_invalidate_erase(Via); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, Via, Via, Via, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_undo_add_obj_to_flag(Via); + PCB_FLAG_TOGGLE(PCB_FLAG_OCTAGON, Via); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_VIA, Via, Via, Via, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_via_invalidate_draw(Via); + return (Via); +} + +/* sets the octagon flag of a via */ +void *pcb_viaop_set_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via) || PCB_FLAG_TEST(PCB_FLAG_OCTAGON, Via)) + return (NULL); + + return (pcb_viaop_change_octagon(ctx, Via)); +} + +/* clears the octagon flag of a via */ +void *pcb_viaop_clear_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via) || !PCB_FLAG_TEST(PCB_FLAG_OCTAGON, Via)) + return (NULL); + + return (pcb_viaop_change_octagon(ctx, Via)); +} + +/* changes the octagon flag of a pin */ +void *pcb_pinop_change_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + pcb_pin_invalidate_erase(Pin); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, Element, Pin, Pin, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_undo_add_obj_to_flag(Pin); + PCB_FLAG_TOGGLE(PCB_FLAG_OCTAGON, Pin); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PIN, Element, Pin, Pin, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_PIN, Element, Pin); + pcb_pin_invalidate_draw(Pin); + return (Pin); +} + +/* sets the octagon flag of a pin */ +void *pcb_pinop_set_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin) || PCB_FLAG_TEST(PCB_FLAG_OCTAGON, Pin)) + return (NULL); + + return (pcb_pinop_change_octagon(ctx, Element, Pin)); +} + +/* clears the octagon flag of a pin */ +void *pcb_pinop_clear_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin) || !PCB_FLAG_TEST(PCB_FLAG_OCTAGON, Pin)) + return (NULL); + + return (pcb_pinop_change_octagon(ctx, Element, Pin)); +} + +/* changes the hole flag of a via */ +pcb_bool pcb_pin_change_hole(pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (pcb_false); + pcb_via_invalidate_erase(Via); + pcb_undo_add_obj_to_flag(Via); + pcb_undo_add_obj_to_mask_size(PCB_TYPE_VIA, Via, Via, Via); + pcb_r_delete_entry(PCB->Data->via_tree, (pcb_box_t *) Via); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + PCB_FLAG_TOGGLE(PCB_FLAG_HOLE, Via); + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, Via)) { + /* A tented via becomes an minimally untented hole. An untented + via retains its mask clearance. */ + if (Via->Mask > Via->Thickness) { + Via->Mask = (Via->DrillingHole + (Via->Mask - Via->Thickness)); + } + else if (Via->Mask < Via->DrillingHole) { + Via->Mask = Via->DrillingHole + 2 * PCB_MASKFRAME; + } + } + else { + Via->Mask = (Via->Thickness + (Via->Mask - Via->DrillingHole)); + } + + pcb_pin_bbox(Via); + pcb_r_insert_entry(PCB->Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_via_invalidate_draw(Via); + pcb_draw(); + return (pcb_true); +} + +/* changes the mask size of a pin */ +void *pcb_pinop_change_mask_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Pin->Mask + ctx->chgsize.value; + + value = MAX(value, 0); + if (value == Pin->Mask && ctx->chgsize.value == 0) + value = Pin->Thickness; + if (value != Pin->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PIN, Element, Pin, Pin); + pcb_pin_invalidate_erase(Pin); + pcb_r_delete_entry(PCB->Data->pin_tree, &Pin->BoundingBox); + Pin->Mask = value; + pcb_element_bbox(PCB->Data, Element, pcb_font(PCB, 0, 1)); + pcb_pin_invalidate_draw(Pin); + return (Pin); + } + return (NULL); +} + +/* changes the mask size of a via */ +void *pcb_viaop_change_mask_size(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value; + + value = (ctx->chgsize.is_absolute) ? ctx->chgsize.value : Via->Mask + ctx->chgsize.value; + value = MAX(value, 0); + if (value != Via->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_VIA, Via, Via, Via); + pcb_via_invalidate_erase(Via); + pcb_r_delete_entry(PCB->Data->via_tree, &Via->BoundingBox); + Via->Mask = value; + pcb_pin_bbox(Via); + pcb_r_insert_entry(PCB->Data->via_tree, &Via->BoundingBox, 0); + pcb_via_invalidate_draw(Via); + return (Via); + } + return (NULL); +} + +/* copies a via */ +void *pcb_viaop_copy(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_pin_t *via; + + via = pcb_via_new(PCB->Data, Via->X + ctx->copy.DeltaX, Via->Y + ctx->copy.DeltaY, + Via->Thickness, Via->Clearance, Via->Mask, Via->DrillingHole, Via->Name, pcb_flag_mask(Via->Flags, PCB_FLAG_FOUND)); + if (!via) + return (via); + pcb_via_invalidate_draw(via); + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + return (via); +} + +/* moves a via */ +void *pcb_viaop_move_noclip(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB->ViaOn) + pcb_via_invalidate_erase(Via); + pcb_via_move(Via, ctx->move.dx, ctx->move.dy); + if (PCB->ViaOn) { + pcb_via_invalidate_draw(Via); + pcb_draw(); + } + return Via; +} + +void *pcb_viaop_move(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_r_delete_entry(PCB->Data->via_tree, (pcb_box_t *) Via); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + pcb_viaop_move_noclip(ctx, Via); + pcb_r_insert_entry(PCB->Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + return Via; +} + +void *pcb_viaop_clip(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (ctx->clip.restore) { + pcb_r_delete_entry(PCB->Data->via_tree, (pcb_box_t *) Via); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(PCB->Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, Via, Via); + } + return Via; +} + + +/* destroys a via */ +void *pcb_viaop_destroy(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_r_delete_entry(ctx->remove.destroy_target->via_tree, (pcb_box_t *) Via); + free(Via->Name); + + pcb_via_free(Via); + return NULL; +} + +/* removes a via */ +void *pcb_viaop_remove(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + /* erase from screen and memory */ + if (PCB->ViaOn) { + pcb_via_invalidate_erase(Via); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_VIA, Via, Via, Via); + return NULL; +} + +void *pcb_viaop_rotate90(pcb_opctx_t *ctx, pcb_pin_t *via) +{ + pcb_data_t *data = via->parent.data; + assert(via->parent_type == PCB_PARENT_DATA); + + pcb_via_invalidate_erase(via); + if (data->via_tree != NULL) { + pcb_poly_restore_to_poly(ctx->rotate.pcb->Data, PCB_TYPE_VIA, via, via); + pcb_r_delete_entry(data->via_tree, (pcb_box_t *)via); + } + PCB_VIA_ROTATE90(via, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + pcb_pin_bbox(via); + if (data->via_tree != NULL) { + pcb_r_insert_entry(data->via_tree, (pcb_box_t *)via, 0); + pcb_poly_clear_from_poly(ctx->rotate.pcb->Data, PCB_TYPE_VIA, via, via); + } + pcb_via_invalidate_draw(via); + return via; +} + +void *pcb_viaop_rotate(pcb_opctx_t *ctx, pcb_pin_t *via) +{ + pcb_data_t *data = via->parent.data; + assert(via->parent_type == PCB_PARENT_DATA); + + pcb_via_invalidate_erase(via); + if (data->via_tree != NULL) { + pcb_poly_restore_to_poly(data, PCB_TYPE_VIA, via, via); + pcb_r_delete_entry(data->via_tree, (pcb_box_t *)via); + } + + pcb_rotate(&via->X, &via->Y, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + + pcb_pin_bbox(via); + if (data->via_tree != NULL) { + pcb_r_insert_entry(data->via_tree, (pcb_box_t *)via, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_VIA, via, via); + } + pcb_via_invalidate_draw(via); + return via; +} + +void *pcb_viaop_change_flag(pcb_opctx_t *ctx, pcb_pin_t *pin) +{ + static pcb_flag_values_t pcb_pin_flags = 0; + if (pcb_pin_flags == 0) + pcb_pin_flags = pcb_obj_valid_flags(PCB_TYPE_PIN); + + if ((ctx->chgflag.flag & pcb_pin_flags) != ctx->chgflag.flag) + return NULL; + if ((ctx->chgflag.flag & PCB_FLAG_TERMNAME) && (pin->term == NULL)) + return NULL; + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, pin); + return pin; +} + +void *pcb_pinop_change_flag(pcb_opctx_t *ctx, pcb_element_t *elem, pcb_pin_t *pin) +{ + return pcb_viaop_change_flag(ctx, pin); +} + +void *pcb_pinop_invalidate_label(pcb_opctx_t *ctx, pcb_pin_t *pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, pin)) + pcb_pin_name_invalidate_erase(pin); + else + pcb_pin_name_invalidate_draw(pin); + return pin; +} + + +/*** draw ***/ + +/* setup color for pin or via */ +static void SetPVColor(pcb_pin_t *Pin, int Type) +{ + char *color; + char buf[sizeof("#XXXXXX")]; + + if ((Type == PCB_TYPE_VIA) && (Pin->term == NULL)) { + /* normal via, not a terminal */ + if (!pcb_draw_doing_pinout && PCB_FLAG_TEST(PCB_FLAG_WARN | PCB_FLAG_SELECTED | PCB_FLAG_FOUND, Pin)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, Pin)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, Pin)) + color = conf_core.appearance.color.via_selected; + else + color = conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, Pin)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + } + else if (PCB_HAS_COLOROVERRIDE(Pin)) { + color = (Pin->override_color); + } else + color = conf_core.appearance.color.via; + } + else { + /* terminal */ + if (!pcb_draw_doing_pinout && PCB_FLAG_TEST(PCB_FLAG_WARN | PCB_FLAG_SELECTED | PCB_FLAG_FOUND, Pin)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, Pin)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, Pin)) + color = conf_core.appearance.color.pin_selected; + else + color = conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, Pin)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + } + else if (PCB_HAS_COLOROVERRIDE(Pin)) { + color = (Pin->override_color); + } + else + color = conf_core.appearance.color.pin; + } + + pcb_gui->set_color(pcb_draw_out.fgGC, color); +} + +static void _draw_pv_name(pcb_pin_t * pv) +{ + pcb_box_t box; + pcb_bool vert; + pcb_coord_t x_off, y_off; + const char *pn; + double scale; + pcb_bool flip_x = conf_core.editor.view.flip_x; + pcb_bool flip_y = conf_core.editor.view.flip_y; + + PCB_DRAW_BBOX(pv); + +#warning subc TODO: remove the name/number logics when elements are removed + if (pv->term != NULL) + pn = pv->term; + else if (!pv->Name || !pv->Name[0]) { /* old: elements */ + pn = PCB_EMPTY(pv->Number); + } + else { /* old: elements */ + pn = PCB_EMPTY(conf_core.editor.show_number ? pv->Number : pv->Name); + if (pn == NULL) + pn = "n/a"; + } + + vert = PCB_FLAG_TEST(PCB_FLAG_EDGE2, pv); + if (vert) { + x_off = -pv->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + y_off = -pv->DrillingHole / 2 - conf_core.appearance.pinout.text_offset_x; + box.X1 = pv->X + (flip_x ? -x_off : x_off); + box.Y1 = pv->Y + (flip_y ? -y_off : y_off); + } + else { + x_off = pv->DrillingHole / 2 + conf_core.appearance.pinout.text_offset_x; + y_off = -pv->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + box.X1 = pv->X + (flip_x ? -x_off : x_off); + box.Y1 = pv->Y + (flip_y ? -y_off : y_off); + } + + /* Set font height to approx 56% of pin thickness */ + scale = 56 * pv->Thickness / PCB_FONT_CAPHEIGHT; + + pcb_term_label_draw(box.X1, box.Y1, scale, vert, pcb_false, pn, pv->intconn); +} + +static void _draw_pv(pcb_pin_t *pv, pcb_bool draw_hole) +{ + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) + pcb_gui->thindraw_pcb_pv(pcb_draw_out.fgGC, pcb_draw_out.fgGC, pv, draw_hole, pcb_false); + else + pcb_gui->fill_pcb_pv(pcb_draw_out.fgGC, pcb_draw_out.drillGC, pv, draw_hole, pcb_false); + + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pv) && pcb_draw_doing_pinout) + _draw_pv_name(pv); +} + +void pcb_pin_draw(pcb_pin_t *pin, pcb_bool draw_hole) +{ + SetPVColor(pin, PCB_TYPE_PIN); + _draw_pv(pin, draw_hole); +} + +pcb_r_dir_t pcb_pin_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_draw((pcb_pin_t *) b, pcb_false); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static void draw_pin_name(pcb_pin_t *pin) +{ + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) && PCB_FLAG_TEST(PCB_FLAG_TERMNAME, pin)) + _draw_pv_name(pin); +} + +pcb_r_dir_t pcb_pin_name_draw_callback(const pcb_box_t * b, void *cl) +{ + draw_pin_name((pcb_pin_t *) b); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_pin_clear_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_t *) b; + if (conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly || conf_core.editor.wireframe_draw) + pcb_gui->thindraw_pcb_pv(pcb_draw_out.pmGC, pcb_draw_out.pmGC, pin, pcb_false, pcb_true); + else + pcb_gui->fill_pcb_pv(pcb_draw_out.pmGC, pcb_draw_out.pmGC, pin, pcb_false, pcb_true); + return PCB_R_DIR_FOUND_CONTINUE; +} + + +static void draw_via(pcb_pin_t *via, pcb_bool draw_hole) +{ + SetPVColor(via, PCB_TYPE_VIA); + _draw_pv(via, draw_hole); +} + +pcb_r_dir_t pcb_via_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *via = (pcb_pin_t *)b; + + if (PCB->SubcPartsOn || !pcb_gobj_parent_subc(via->parent_type, &via->parent)) + draw_via(via, pcb_false); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t pcb_hole_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pv = (pcb_pin_t *) b; + int plated = cl ? *(int *) cl : -1; + const char *color; + char buf[sizeof("#XXXXXX")]; + + if ((plated == 0 && !PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) || (plated == 1 && PCB_FLAG_TEST(PCB_FLAG_HOLE, pv))) + return PCB_R_DIR_FOUND_CONTINUE; + + if (!PCB->SubcPartsOn && pcb_gobj_parent_subc(pv->parent_type, &pv->parent)) + return PCB_R_DIR_FOUND_CONTINUE; + + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) { + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Round_Cap); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->draw_arc(pcb_draw_out.fgGC, pv->X, pv->Y, pv->DrillingHole / 2, pv->DrillingHole / 2, 0, 360); + } + } + else + pcb_gui->fill_circle(pcb_draw_out.drillGC, pv->X, pv->Y, pv->DrillingHole / 2); + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, pv)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pv)) + color = conf_core.appearance.color.via_selected; + else + color = conf_core.appearance.color.black; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, pv)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + pcb_gui->set_color(pcb_draw_out.fgGC, color); + + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Round_Cap); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->draw_arc(pcb_draw_out.fgGC, pv->X, pv->Y, pv->DrillingHole / 2, pv->DrillingHole / 2, 0, 360); + } + return PCB_R_DIR_FOUND_CONTINUE; +} + +static void GatherPVName(pcb_pin_t *Ptr) +{ + pcb_box_t box; + pcb_bool vert = PCB_FLAG_TEST(PCB_FLAG_EDGE2, Ptr); + + if (vert) { + box.X1 = Ptr->X - Ptr->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + box.Y1 = Ptr->Y - Ptr->DrillingHole / 2 - conf_core.appearance.pinout.text_offset_x; + } + else { + box.X1 = Ptr->X + Ptr->DrillingHole / 2 + conf_core.appearance.pinout.text_offset_x; + box.Y1 = Ptr->Y - Ptr->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + } + + if (vert) { + box.X2 = box.X1; + box.Y2 = box.Y1; + } + else { + box.X2 = box.X1; + box.Y2 = box.Y1; + } + pcb_draw_invalidate(&box); +} + +void pcb_via_invalidate_erase(pcb_pin_t *Via) +{ + pcb_draw_invalidate(Via); + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Via)) + pcb_via_name_invalidate_erase(Via); + pcb_flag_erase(&Via->Flags); +} + +void pcb_via_name_invalidate_erase(pcb_pin_t *Via) +{ + GatherPVName(Via); +} + +void pcb_pin_invalidate_erase(pcb_pin_t *Pin) +{ + pcb_draw_invalidate(Pin); + if (PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pin)) + pcb_pin_name_invalidate_erase(Pin); + pcb_flag_erase(&Pin->Flags); +} + +void pcb_pin_name_invalidate_erase(pcb_pin_t *Pin) +{ + GatherPVName(Pin); +} + +void pcb_via_invalidate_draw(pcb_pin_t *Via) +{ + pcb_draw_invalidate(Via); + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, Via) && PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Via)) + pcb_via_name_invalidate_draw(Via); +} + +void pcb_via_name_invalidate_draw(pcb_pin_t *Via) +{ + GatherPVName(Via); +} + +void pcb_pin_invalidate_draw(pcb_pin_t *Pin) +{ + pcb_draw_invalidate(Pin); + if ((!PCB_FLAG_TEST(PCB_FLAG_HOLE, Pin) && PCB_FLAG_TEST(PCB_FLAG_TERMNAME, Pin)) + || pcb_draw_doing_pinout) + pcb_pin_name_invalidate_draw(Pin); +} + +void pcb_pin_name_invalidate_draw(pcb_pin_t *Pin) +{ + GatherPVName(Pin); +} Index: tags/1.2.7/src/obj_pinvia.h =================================================================== --- tags/1.2.7/src/obj_pinvia.h (nonexistent) +++ tags/1.2.7/src/obj_pinvia.h (revision 13657) @@ -0,0 +1,140 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: pins and vias */ + +#ifndef PCB_OBJ_PINVIA_H +#define PCB_OBJ_PINVIA_H + +#include "obj_common.h" + +struct pcb_pin_s { + PCB_ANYOBJECTFIELDS; + pcb_coord_t Thickness, Clearance, Mask, DrillingHole; + pcb_coord_t X, Y; /* center and diameter */ + char *Name, *Number; + void *Element; + gdl_elem_t link; /* a pin is in a list (element) */ +}; + + +pcb_pin_t *pcb_via_alloc(pcb_data_t * data); +void pcb_via_free(pcb_pin_t * data); +pcb_pin_t *pcb_pin_alloc(pcb_element_t * element); +void pcb_pin_free(pcb_pin_t * data); + +pcb_pin_t *pcb_via_new(pcb_data_t *Data, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_coord_t Mask, pcb_coord_t DrillingHole, const char *Name, pcb_flag_t Flags); +pcb_pin_t *pcb_via_dup(pcb_data_t *data, pcb_pin_t *src); +pcb_pin_t *pcb_via_dup_at(pcb_data_t *data, pcb_pin_t *src, pcb_coord_t dx, pcb_coord_t dy); +pcb_pin_t *pcb_element_pin_new(pcb_element_t *Element, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Thickness, pcb_coord_t Clearance, pcb_coord_t Mask, pcb_coord_t DrillingHole, const char *Name, const char *Number, pcb_flag_t Flags); +void pcb_add_via(pcb_data_t *Data, pcb_pin_t *Via); +void pcb_pin_bbox(pcb_pin_t *Pin); + +/* return the net copper bounding box in out */ +void pcb_pin_copper_bbox(pcb_box_t *out, pcb_pin_t *Pin); + + +void pcb_via_rotate(pcb_data_t *Data, pcb_pin_t *Via, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +void pcb_via_mirror(pcb_data_t *Data, pcb_pin_t *Via, pcb_coord_t y_offs); +void pcb_via_flip_side(pcb_data_t *Data, pcb_pin_t *via); + +/* hash */ +int pcb_pin_eq(const pcb_element_t *e1, const pcb_pin_t *p1, const pcb_element_t *e2, const pcb_pin_t *p2); +int pcb_pin_eq_padstack(const pcb_pin_t *p1, const pcb_pin_t *p2); +unsigned int pcb_pin_hash(const pcb_element_t *e, const pcb_pin_t *p); +unsigned int pcb_pin_hash_padstack(const pcb_pin_t *p); + + +pcb_bool pcb_pin_change_hole(pcb_pin_t *Via); + +/* This is the extents of a Pin or Via, depending on whether it's a + hole or not. */ +#define PIN_SIZE(pinptr) \ + (PCB_FLAG_TEST(PCB_FLAG_HOLE, (pinptr)) \ + ? (pinptr)->DrillingHole \ + : (pinptr)->Thickness) + + +#define pcb_via_move(v,dx,dy) \ + do { \ + pcb_coord_t __dx__ = (dx), __dy__ = (dy); \ + pcb_pin_t *__v__ = (v); \ + PCB_MOVE((__v__)->X,(__v__)->Y,(__dx__),(__dy__)) \ + PCB_BOX_MOVE_LOWLEVEL(&((__v__)->BoundingBox),(__dx__),(__dy__)); \ + } while(0) + +#define pcb_pin_move(p,dx,dy) pcb_via_move(p, dx, dy) + +/* Rotate pin shape style by n_in * 90 degrees */ +#define PCB_PIN_ROTATE_SHAPE(p,n_in) \ +do { \ + int _n_; \ + for(_n_ = n_in;_n_>0;_n_--) { \ + int _old_, _nw_ = 0; \ + _old_ = PCB_FLAG_SQUARE_GET(p); \ + if ((_old_ > 1) && (_old_ < 17)) { \ + _old_--; \ + if (_old_ & 1) \ + _nw_ |= 8; \ + if (_old_ & 8) \ + _nw_ |= 2; \ + if (_old_ & 2) \ + _nw_ |= 4; \ + if (_old_ & 4) \ + _nw_ |= 1; \ + PCB_FLAG_SQUARE_GET(p) = _nw_+1; \ + } \ + } \ +} while(0) + +#define PCB_VIA_ROTATE90(v,x0,y0,n) \ +do { \ + PCB_COORD_ROTATE90((v)->X,(v)->Y,(x0),(y0),(n)); \ + PCB_PIN_ROTATE_SHAPE(v, (n)); \ +} while(0) + +#define PCB_PIN_ROTATE90(p,x0,y0,n) \ +do { \ + PCB_COORD_ROTATE90((p)->X,(p)->Y,(x0),(y0),(n)); \ + PCB_PIN_ROTATE_SHAPE((p), (n)); \ +} while(0) + + +#define PCB_VIA_LOOP(top) do { \ + pcb_pin_t *via; \ + gdl_iterator_t __it__; \ + pinlist_foreach(&(top)->Via, &__it__, via) { + +#define PCB_PIN_LOOP(element) do { \ + pcb_pin_t *pin; \ + gdl_iterator_t __it__; \ + pinlist_foreach(&(element)->Pin, &__it__, pin) { + +#define PCB_PIN_ALL_LOOP(top) \ + PCB_ELEMENT_LOOP(top); \ + PCB_PIN_LOOP(element) \ + +#endif Index: tags/1.2.7/src/obj_pinvia_draw.h =================================================================== --- tags/1.2.7/src/obj_pinvia_draw.h (nonexistent) +++ tags/1.2.7/src/obj_pinvia_draw.h (revision 13657) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw on pins and vias ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t pcb_pin_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_pin_name_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_pin_clear_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_via_draw_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t pcb_hole_draw_callback(const pcb_box_t * b, void *cl); +#endif + + +void pcb_pin_draw(pcb_pin_t *pin, pcb_bool draw_hole); +void pcb_via_invalidate_erase(pcb_pin_t *Via); +void pcb_via_name_invalidate_erase(pcb_pin_t *Via); +void pcb_pin_invalidate_erase(pcb_pin_t *Pin); +void pcb_pin_name_invalidate_erase(pcb_pin_t *Pin); +void pcb_via_invalidate_draw(pcb_pin_t *Via); +void pcb_via_name_invalidate_draw(pcb_pin_t *Via); +void pcb_pin_invalidate_draw(pcb_pin_t *Pin); +void pcb_pin_name_invalidate_draw(pcb_pin_t *Pin); Index: tags/1.2.7/src/obj_pinvia_list.c =================================================================== --- tags/1.2.7/src/obj_pinvia_list.c (nonexistent) +++ tags/1.2.7/src/obj_pinvia_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_pinvia_list.h" +#include Index: tags/1.2.7/src/obj_pinvia_list.h =================================================================== --- tags/1.2.7/src/obj_pinvia_list.h (nonexistent) +++ tags/1.2.7/src/obj_pinvia_list.h (revision 13657) @@ -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. + * + */ + +#ifndef PCB_OBJ_PINVIA_LIST_H +#define PCB_OBJ_PINVIA_LIST_H + +#include "obj_pinvia.h" + +/* List of Pins */ +#define TDL(x) pinlist_ ## x +#define TDL_LIST_T pinlist_t +#define TDL_ITEM_T pcb_pin_t +#define TDL_FIELD link +#define TDL_SIZE_T size_t +#define TDL_FUNC + +#define pinlist_foreach(list, iterator, loop_elem) \ + gdl_foreach_((&((list)->lst)), (iterator), (loop_elem)) + +#include +#include + +#endif Index: tags/1.2.7/src/obj_pinvia_op.h =================================================================== --- tags/1.2.7/src/obj_pinvia_op.h (nonexistent) +++ tags/1.2.7/src/obj_pinvia_op.h (revision 13657) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard operations on pins and vias ***/ + +#include "operation.h" + +void *pcb_viaop_add_to_buffer(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_move_to_buffer(pcb_opctx_t *ctx, pcb_pin_t * via); +void *pcb_viaop_change_thermal(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_thermal(pcb_opctx_t *ctx, pcb_element_t *element, pcb_pin_t *Pin); +void *pcb_viaop_change_size(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_change_2nd_size(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_2nd_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_viaop_change_clear_size(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_change_clear_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_viaop_change_name(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_name(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_change_num(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_viaop_change_square(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_set_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_clear_square(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_viaop_change_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_set_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_clear_octagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_pinop_change_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_set_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_pinop_clear_octagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +pcb_bool pcb_pin_change_hole(pcb_pin_t *Via); +void *pcb_pinop_change_mask_size(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *pcb_viaop_change_mask_size(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_copy(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_move(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_move_noclip(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_clip(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_destroy(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_remove(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *pcb_viaop_change_flag(pcb_opctx_t *ctx, pcb_pin_t *pin); +void *pcb_pinop_change_flag(pcb_opctx_t *ctx, pcb_element_t *elem, pcb_pin_t *pin); +void *pcb_viaop_rotate90(pcb_opctx_t *ctx, pcb_pin_t *via); +void *pcb_viaop_rotate(pcb_opctx_t *ctx, pcb_pin_t *via); +void *pcb_pinop_invalidate_label(pcb_opctx_t *ctx, pcb_pin_t *pin); + Index: tags/1.2.7/src/obj_pinvia_therm.c =================================================================== --- tags/1.2.7/src/obj_pinvia_therm.c (nonexistent) +++ tags/1.2.7/src/obj_pinvia_therm.c (revision 13657) @@ -0,0 +1,449 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* negative thermal finger polygons */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "polygon.h" +#include "obj_pinvia_therm.h" + +#warning cleanup TODO: remove this, pass on pcb as arg instead +static pcb_board_t *pcb; + +struct cent { + pcb_coord_t x, y; + pcb_coord_t s, c; + char style; + pcb_polyarea_t *p; +}; + +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); +} + +static pcb_polyarea_t *square_therm(pcb_pin_t *pin, pcb_cardinal_t style) +{ + pcb_polyarea_t *p, *p2; + pcb_pline_t *c; + pcb_vector_t v; + pcb_coord_t d, in, out; + + switch (style) { + case 1: + d = pcb->ThermScale * pin->Clearance * M_SQRT1_2; + out = (pin->Thickness + pin->Clearance) / 2; + in = pin->Thickness / 2; + /* top (actually bottom since +y is down) */ + v[0] = pin->X - in + d; + v[1] = pin->Y + in; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = pin->X + in - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X + out - d; + v[1] = pin->Y + out; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X - out + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + p = pcb_poly_from_contour(c); + /* right */ + v[0] = pin->X + in; + v[1] = pin->Y + in - d; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[1] = pin->Y - in + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X + out; + v[1] = pin->Y - out + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[1] = pin->Y + out - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + p2 = pcb_poly_from_contour(c); + p->f = p2; + p2->b = p; + /* left */ + v[0] = pin->X - in; + v[1] = pin->Y - in + d; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[1] = pin->Y + in - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X - out; + v[1] = pin->Y + out - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[1] = pin->Y - out + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + p2 = pcb_poly_from_contour(c); + p->f->f = p2; + p2->b = p->f; + /* bottom (actually top since +y is down) */ + v[0] = pin->X + in - d; + v[1] = pin->Y - in; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = pin->X - in + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X - out + d; + v[1] = pin->Y - out; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X + out - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + p2 = pcb_poly_from_contour(c); + p->f->f->f = p2; + p2->f = p; + p2->b = p->f->f; + p->b = p2; + return p; + case 4: + { + pcb_line_t l; + l.Flags = pcb_no_flags(); + d = pin->Thickness / 2 - pcb->ThermScale * pin->Clearance; + out = pin->Thickness / 2 + pin->Clearance / 4; + in = pin->Clearance / 2; + /* top */ + l.Point1.X = pin->X - d; + l.Point2.Y = l.Point1.Y = pin->Y + out; + l.Point2.X = pin->X + d; + p = pcb_poly_from_line(&l, in); + /* right */ + l.Point1.X = l.Point2.X = pin->X + out; + l.Point1.Y = pin->Y - d; + l.Point2.Y = pin->Y + d; + p2 = pcb_poly_from_line(&l, in); + p->f = p2; + p2->b = p; + /* bottom */ + l.Point1.X = pin->X - d; + l.Point2.Y = l.Point1.Y = pin->Y - out; + l.Point2.X = pin->X + d; + p2 = pcb_poly_from_line(&l, in); + p->f->f = p2; + p2->b = p->f; + /* left */ + l.Point1.X = l.Point2.X = pin->X - out; + l.Point1.Y = pin->Y - d; + l.Point2.Y = pin->Y + d; + p2 = pcb_poly_from_line(&l, in); + p->f->f->f = p2; + p2->b = p->f->f; + p->b = p2; + p2->f = p; + return p; + } + default: /* style 2 and 5 */ + d = 0.5 * pcb->ThermScale * pin->Clearance; + if (style == 5) + d += d; + out = (pin->Thickness + pin->Clearance) / 2; + in = pin->Thickness / 2; + /* topright */ + v[0] = pin->X + in; + v[1] = pin->Y + in; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[1] = pin->Y + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 2) { + v[0] = pin->X + out; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + else + pcb_poly_frac_circle(c, v[0] + pin->Clearance / 4, v[1], v, 2); + v[1] = pin->Y + in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + /* pivot 1/4 circle to next point */ + pcb_poly_frac_circle(c, pin->X + in, pin->Y + in, v, 4); + v[0] = pin->X + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 2) { + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[1] = pin->Y + in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + else + pcb_poly_frac_circle(c, v[0], v[1] - pin->Clearance / 4, v, 2); + p = pcb_poly_from_contour(c); + /* bottom right */ + v[0] = pin->X + in; + v[1] = pin->Y - d; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[1] = pin->Y - in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 2) { + v[1] = pin->Y - out; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + else + pcb_poly_frac_circle(c, v[0], v[1] - pin->Clearance / 4, v, 2); + v[0] = pin->X + in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + /* pivot 1/4 circle to next point */ + pcb_poly_frac_circle(c, pin->X + in, pin->Y - in, v, 4); + v[1] = pin->Y - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 5) + pcb_poly_frac_circle(c, v[0] - pin->Clearance / 4, v[1], v, 2); + p2 = pcb_poly_from_contour(c); + p->f = p2; + p2->b = p; + /* bottom left */ + v[0] = pin->X - d; + v[1] = pin->Y - in; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = pin->X - in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[1] = pin->Y - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 2) { + v[0] = pin->X - out; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + else + pcb_poly_frac_circle(c, v[0] - pin->Clearance / 4, v[1], v, 2); + v[1] = pin->Y - in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + /* pivot 1/4 circle to next point */ + pcb_poly_frac_circle(c, pin->X - in, pin->Y - in, v, 4); + v[0] = pin->X - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 5) + pcb_poly_frac_circle(c, v[0], v[1] + pin->Clearance / 4, v, 2); + p2 = pcb_poly_from_contour(c); + p->f->f = p2; + p2->b = p->f; + /* top left */ + v[0] = pin->X - d; + v[1] = pin->Y + out; + if ((c = pcb_poly_contour_new(v)) == NULL) + return NULL; + v[0] = pin->X - in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + /* pivot 1/4 circle to next point (x-out, y+in) */ + pcb_poly_frac_circle(c, pin->X - in, pin->Y + in, v, 4); + v[1] = pin->Y + d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 2) { + v[0] = pin->X - in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + } + else + pcb_poly_frac_circle(c, v[0] + pin->Clearance / 4, v[1], v, 2); + v[1] = pin->Y + in; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + v[0] = pin->X - d; + pcb_poly_vertex_include(c->head.prev, pcb_poly_node_create(v)); + if (style == 5) + pcb_poly_frac_circle(c, v[0], v[1] + pin->Clearance / 4, v, 2); + p2 = pcb_poly_from_contour(c); + p->f->f->f = p2; + p2->f = p; + p2->b = p->f->f; + p->b = p2; + return p; + } +} + +static pcb_polyarea_t *oct_therm(pcb_pin_t *pin, pcb_cardinal_t style) +{ + pcb_polyarea_t *p, *p2, *m; + pcb_coord_t t = 0.5 * pcb->ThermScale * pin->Clearance; + pcb_coord_t w = pin->Thickness + pin->Clearance; + int shape = PCB_FLAG_SQUARE_GET(pin); + + /* temporary work around corner case on square+octagon shape with large clearance */ + if (shape <= 1) + shape = 17; + + p = pcb_poly_from_octagon(pin->X, pin->Y, w, shape); + p2 = pcb_poly_from_octagon(pin->X, pin->Y, pin->Thickness, shape); + /* make full clearance ring */ + pcb_polyarea_boolean_free(p, p2, &m, PCB_PBO_SUB); + switch (style) { + default: + case 1: + p = pcb_pa_diag_line(pin->X, pin->Y, w, t, pcb_true); + pcb_polyarea_boolean_free(m, p, &p2, PCB_PBO_SUB); + p = pcb_pa_diag_line(pin->X, pin->Y, w, t, pcb_false); + pcb_polyarea_boolean_free(p2, p, &m, PCB_PBO_SUB); + return m; + case 2: + p = pcb_poly_from_rect(pin->X - t, pin->X + t, pin->Y - w, pin->Y + w); + pcb_polyarea_boolean_free(m, p, &p2, PCB_PBO_SUB); + p = pcb_poly_from_rect(pin->X - w, pin->X + w, pin->Y - t, pin->Y + t); + pcb_polyarea_boolean_free(p2, p, &m, PCB_PBO_SUB); + return m; + /* fix me add thermal style 4 */ + case 5: + { + pcb_coord_t t = pin->Thickness / 2; + pcb_polyarea_t *q; + /* cheat by using the square therm's rounded parts */ + p = square_therm(pin, style); + q = pcb_poly_from_rect(pin->X - t, pin->X + t, pin->Y - t, pin->Y + t); + pcb_polyarea_boolean_free(p, q, &p2, PCB_PBO_UNITE); + pcb_polyarea_boolean_free(m, p2, &p, PCB_PBO_ISECT); + return p; + } + } +} + +/* 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; + } +} + +pcb_polyarea_t *ThermPoly(pcb_board_t *p, pcb_pin_t *pin, pcb_cardinal_t laynum) +{ + pcb_cardinal_t style = PCB_FLAG_THERM_GET(laynum, pin); + if (style == 3) + return NULL; /* solid connection no clearance */ + pcb = p; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) + return square_therm(pin, style); + if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pin)) + return oct_therm(pin, style); + + return ThermPoly_(p, pin->X, pin->Y, pin->Thickness, pin->Clearance, style); +} Index: tags/1.2.7/src/obj_pinvia_therm.h =================================================================== --- tags/1.2.7/src/obj_pinvia_therm.h (nonexistent) +++ tags/1.2.7/src/obj_pinvia_therm.h (revision 13657) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* thermal on pins/vias + * + * Thermals are normal lines on the layout. The only thing unique + * about them is that they have the PCB_FLAG_USETHERMAL set so that they + * can be identified as thermals. It is handy for pcb to automatically + * make adjustments to the thermals when the user performs certain + * operations, and the functions in thermal.h help implement that. + */ + +#ifndef PCB_PINVIA_THERMAL_H +#define PCB_PINVIA_THERMAL_H + +#include +#include "config.h" + +pcb_polyarea_t *ThermPoly(pcb_board_t *, pcb_pin_t *, pcb_cardinal_t); +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/1.2.7/src/obj_poly.c =================================================================== --- tags/1.2.7/src/obj_poly.c (nonexistent) +++ tags/1.2.7/src/obj_poly.c (revision 13657) @@ -0,0 +1,1094 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: polygons */ + + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "compat_nls.h" +#include "undo.h" +#include "polygon.h" +#include "polygon_offs.h" +#include "rotate.h" +#include "search.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" + +/* TODO: get rid of these: */ +#include "draw.h" + +#define STEP_POLYGONPOINT 10 +#define STEP_POLYGONHOLEINDEX 10 + +/*** allocation ***/ + +/* get next slot for a polygon object, allocates memory if necessary */ +pcb_poly_t *pcb_poly_alloc(pcb_layer_t * layer) +{ + pcb_poly_t *new_obj; + + new_obj = calloc(sizeof(pcb_poly_t), 1); + new_obj->type = PCB_OBJ_POLY; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, layer, layer); + + polylist_append(&layer->Polygon, new_obj); + + return new_obj; +} + +void pcb_poly_free(pcb_poly_t * data) +{ + polylist_remove(data); + free(data); +} + +/* 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) +{ + if (polygon == NULL) + return; + + free(polygon->Points); + free(polygon->HoleIndex); + + if (polygon->Clipped) + pcb_polyarea_free(&polygon->Clipped); + pcb_poly_contours_free(&polygon->NoHoles); + + reset_obj_mem(pcb_poly_t, polygon); +} + +/*** 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_POLY_POINT_LOOP(Polygon); + { + PCB_COORD_ROTATE90(point->X, point->Y, X, Y, Number); + } + PCB_END_LOOP; + + /* 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) +{ + 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; + pcb_poly_bbox(polygon); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon, 0); +} + +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; + pcb_poly_bbox(polygon); + if (layer->polygon_tree != NULL) + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *)polygon, 0); +} + +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; + pcb_poly_bbox(polygon); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon, 0); + /* hmmm, how to handle clip */ +} + + +/* sets the bounding box of a polygons */ +void pcb_poly_bbox(pcb_poly_t *Polygon) +{ + Polygon->BoundingBox.X1 = Polygon->BoundingBox.Y1 = PCB_MAX_COORD; + Polygon->BoundingBox.X2 = Polygon->BoundingBox.Y2 = -PCB_MAX_COORD; + PCB_POLY_POINT_LOOP(Polygon); + { + PCB_MAKE_MIN(Polygon->BoundingBox.X1, point->X); + PCB_MAKE_MIN(Polygon->BoundingBox.Y1, point->Y); + PCB_MAKE_MAX(Polygon->BoundingBox.X2, point->X); + PCB_MAKE_MAX(Polygon->BoundingBox.Y2, point->Y); + } + /* boxes don't include the lower right corner */ + pcb_close_box(&Polygon->BoundingBox); + PCB_END_LOOP; +} + +/* 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(NULL, 0, 0); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) polygon, 0); + PCB_SET_PARENT(polygon, layer, Layer); + pcb_poly_clear_from_poly(Layer->parent, PCB_TYPE_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->ID = pcb_create_ID_get(); + 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); + 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); + 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; + 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(NULL, 0, 0); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *) polygon, 0); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND | ctx->buffer.extraflg, polygon); + return (polygon); +} + + +/* moves a polygon to buffer. Doesn't allocate memory for the points */ +void *pcb_polyop_move_to_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_poly_t * polygon) +{ + pcb_layer_t *lay = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, layer)]; + + pcb_poly_pprestore(polygon); + + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *) polygon); + + polylist_remove(polygon); + polylist_append(&lay->Polygon, polygon); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, polygon); + + if (!lay->polygon_tree) + lay->polygon_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(lay->polygon_tree, (pcb_box_t *) polygon, 0); + + PCB_SET_PARENT(polygon, layer, lay); + + 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) +{ + static int shown_this_message = 0; + if (!shown_this_message) { + pcb_gui->confirm_dialog(_("To change the clearance of objects in a polygon, " + "change the objects, not the polygon.\n" + "Hint: To set a minimum clearance for a group of objects, " + "select them all then :MinClearGap(Selected,=10,mil)"), "Ok", NULL); + shown_this_message = 1; + } + + 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_TYPE_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_TYPE_POLY_POINT, Layer, Polygon, &Polygon->Points[ctx->insert.idx]); + + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + 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_draw(); + } + + 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_TYPE_POLY, Layer, poly, poly, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_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_TYPE_POLY, Layer, poly, poly, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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->X, point->Y, DX, DY); + } + PCB_END_LOOP; + PCB_BOX_MOVE_LOWLEVEL(&Polygon->BoundingBox, 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); + pcb_draw(); + } + 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, 0); + 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, 0); + 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->X, Point->Y, ctx->move.dx, ctx->move.dy); + pcb_poly_bbox(Polygon); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + 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_draw(); + } + 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); + polylist_remove(polygon); + polylist_append(&Destination->Polygon, polygon); + + if (!Destination->polygon_tree) + Destination->polygon_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(Destination->polygon_tree, (pcb_box_t *) polygon, 0); + + PCB_SET_PARENT(polygon, layer, Destination); + pcb_poly_ppclear(polygon); + return polygon; +} + +struct mptlc { + pcb_layer_id_t snum, dnum; + int type; + pcb_poly_t *polygon; +} mptlc; + +pcb_r_dir_t mptl_pin_callback(const pcb_box_t * b, void *cl) +{ + struct mptlc *d = (struct mptlc *) cl; + pcb_pin_t *pin = (pcb_pin_t *) b; + if (!PCB_FLAG_THERM_TEST(d->snum, pin) || !pcb_poly_is_point_in_p(pin->X, pin->Y, pin->Thickness + pin->Clearance + 2, d->polygon)) + return PCB_R_DIR_NOT_FOUND; + if (d->type == PCB_TYPE_PIN) + pcb_undo_add_obj_to_flag(pin); + else + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_THERM_ASSIGN(d->dnum, PCB_FLAG_THERM_GET(d->snum, pin), pin); + PCB_FLAG_THERM_CLEAR(d->snum, pin); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* 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; + struct mptlc d; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Polygon)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + return NULL; + } + if (Layer == ctx->move.dst_layer) + return (Polygon); + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_POLY, Layer, Polygon, Polygon); + if (Layer->meta.real.vis) + pcb_poly_invalidate_erase(Polygon); + /* Move all of the thermals with the polygon */ + d.snum = pcb_layer_id(PCB->Data, Layer); + d.dnum = pcb_layer_id(PCB->Data, ctx->move.dst_layer); + d.polygon = Polygon; + d.type = PCB_TYPE_PIN; + pcb_r_search(PCB->Data->pin_tree, &Polygon->BoundingBox, NULL, mptl_pin_callback, &d, NULL); + d.type = PCB_TYPE_VIA; + pcb_r_search(PCB->Data->via_tree, &Polygon->BoundingBox, NULL, mptl_pin_callback, &d, NULL); + 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); + pcb_draw(); + } + 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, 0); + 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); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_POLY, Layer, Polygon, Polygon); + return NULL; +} + +void *pcb_poly_remove(pcb_layer_t *Layer, pcb_poly_t *Polygon) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + return pcb_polyop_remove(&ctx, Layer, Polygon); +} + +/* 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); + if (!ctx->remove.bulk) + pcb_draw(); + } + + /* Copy the polygon to the undo list */ + pcb_undo_add_obj_to_remove_contour(PCB_TYPE_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); + if (!ctx->remove.bulk) + pcb_draw(); + } + 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_TYPE_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, 0); + 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); + if (!ctx->remove.bulk) + pcb_draw(); + } + + 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(NULL, 0, 0); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) polygon, 0); + pcb_poly_init_clip(PCB->Data, Layer, polygon); + pcb_poly_invalidate_draw(Layer, polygon); + pcb_undo_add_obj_to_create(PCB_TYPE_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); + 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); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->meta.real.vis) { + pcb_poly_invalidate_draw(Layer, Polygon); + pcb_draw(); + } + 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_draw(); + } + 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_TYPE_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_TYPE_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_TYPE_POLY, Polygon->parent.layer, Polygon); + + return Polygon; +} + + +/*** 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_text_t text; + pcb_term_label_setup(&text, (poly->BoundingBox.X1 + poly->BoundingBox.X2)/2, (poly->BoundingBox.Y1 + poly->BoundingBox.Y2)/2, + 100.0, is_poly_term_vert(poly), pcb_true, poly->term, poly->intconn); + pcb_draw_invalidate(&text); + } +} + +void pcb_poly_draw_label(pcb_poly_t *poly) +{ + if (poly->term != NULL) + pcb_term_label_draw((poly->BoundingBox.X1 + poly->BoundingBox.X2)/2, (poly->BoundingBox.Y1 + poly->BoundingBox.Y2)/2, + 100.0, is_poly_term_vert(poly), pcb_true, poly->term, poly->intconn); +} + +void pcb_poly_draw_(pcb_poly_t *polygon, const pcb_box_t *drawn_area, int allow_term_gfx) +{ + 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, drawn_area); + } + else { + if ((allow_term_gfx) && pcb_draw_term_need_gfx(polygon)) { + pcb_vnode_t *n, *head; + int i; + + pcb_gui->fill_pcb_polygon(pcb_draw_out.active_padGC, polygon, drawn_area); + head = &polygon->Clipped->contours->head; + + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Square_Cap); + 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; + +#warning subc TODO: check if x;y is within the poly, but use a cheaper method than the official + r = PCB_DRAW_TERM_GFX_WIDTH; + pcb_gui->set_line_width(pcb_draw_out.fgGC, r); + pcb_gui->draw_line(pcb_draw_out.fgGC, x, y, x, y); + } + } + else + pcb_gui->fill_pcb_polygon(pcb_draw_out.fgGC, polygon, 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, drawn_area); + } + + if (polygon->term != NULL) { + if ((pcb_draw_doing_pinout) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, polygon)) + pcb_draw_delay_label_add((pcb_any_obj_t *)polygon); + } +} + +static void pcb_poly_draw(pcb_layer_t *layer, pcb_poly_t *polygon, const pcb_box_t *drawn_area, int allow_term_gfx) +{ + static const char *color; + char buf[sizeof("#XXXXXX")]; + + if (PCB_FLAG_TEST(PCB_FLAG_WARN, polygon)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) + color = layer->meta.real.selected_color; + else if (PCB_FLAG_TEST(PCB_FLAG_FOUND, polygon)) + color = conf_core.appearance.color.connected; + else if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, polygon)) { + assert(color != NULL); + 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); + else + color = layer->meta.real.color; + pcb_gui->set_color(pcb_draw_out.fgGC, color); + + pcb_poly_draw_(polygon, drawn_area, 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 (!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->layer, polygon, i->drawn_area, 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 (!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->layer, polygon, i->drawn_area, 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/1.2.7/src/obj_poly.h =================================================================== --- tags/1.2.7/src/obj_poly.h (nonexistent) +++ tags/1.2.7/src/obj_poly.h (revision 13657) @@ -0,0 +1,275 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: polygons */ + +#ifndef PCB_OBJ_POLY_H +#define PCB_OBJ_POLY_H + +#include "obj_common.h" +#include "polyarea.h" + +struct pcb_poly_s { /* holds information about a polygon */ + PCB_ANYOBJECTFIELDS; + 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() */ + gdl_elem_t link; /* a poly is in a list of a layer */ +}; + + + +pcb_poly_t *pcb_poly_alloc(pcb_layer_t * layer); +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_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_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); + +/* 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); + +/* 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->parent_type == PCB_PARENT_BOARD)) { \ + if (layer->is_bound) layer = layer->meta.bound.real; \ + if (PCB_POLY_HAS_CLEARANCE(poly) && (layer != NULL)) \ + pcb_poly_clear_from_poly(layer->parent, PCB_TYPE_POLY, layer, poly); \ + } \ + } \ +} 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->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, PCB_TYPE_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/1.2.7/src/obj_poly_draw.h =================================================================== --- tags/1.2.7/src/obj_poly_draw.h (nonexistent) +++ tags/1.2.7/src/obj_poly_draw.h (revision 13657) @@ -0,0 +1,39 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw of polygons ***/ + +/* 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_poly_t *poly); + Index: tags/1.2.7/src/obj_poly_list.c =================================================================== --- tags/1.2.7/src/obj_poly_list.c (nonexistent) +++ tags/1.2.7/src/obj_poly_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_poly_list.h" +#include Index: tags/1.2.7/src/obj_poly_list.h =================================================================== --- tags/1.2.7/src/obj_poly_list.h (nonexistent) +++ tags/1.2.7/src/obj_poly_list.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_poly_op.h =================================================================== --- tags/1.2.7/src/obj_poly_op.h (nonexistent) +++ tags/1.2.7/src/obj_poly_op.h (revision 13657) @@ -0,0 +1,54 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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_to_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/1.2.7/src/obj_pstk.c =================================================================== --- tags/1.2.7/src/obj_pstk.c (nonexistent) +++ tags/1.2.7/src/obj_pstk.c (revision 13657) @@ -0,0 +1,958 @@ +/* + * 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. + * + */ + +#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 "operation.h" +#include "search.h" +#include "undo.h" +#include "vtpadstack.h" + +#define PS_CROSS_SIZE PCB_MM_TO_COORD(1) + +#define SQR(o) ((o)*(o)) + +static const char core_pstk_cookie[] = "padstack"; + +pcb_pstk_t *pcb_pstk_alloc(pcb_data_t *data) +{ + pcb_pstk_t *ps; + + ps = calloc(sizeof(pcb_pstk_t), 1); + ps->protoi = -1; + ps->type = PCB_OBJ_PSTK; + ps->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(ps, data, data); + + padstacklist_append(&data->padstack, ps); + + return ps; +} + +void pcb_pstk_free(pcb_pstk_t *ps) +{ + padstacklist_remove(ps); + free(ps->thermals.shape); + free(ps); +} + +pcb_pstk_t *pcb_pstk_new_tr(pcb_data_t *data, 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; + + ps = pcb_pstk_alloc(data); + + /* copy values */ + ps->proto = proto; + ps->x = x; + ps->y = y; + ps->Clearance = clearance; + ps->Flags = Flags; + ps->ID = pcb_create_ID_get(); + ps->rot = rot; + ps->xmirror = xmirror; + ps->smirror = smirror; + pcb_pstk_add(data, ps); + pcb_poly_clear_from_poly(data, PCB_TYPE_PSTK, NULL, ps); + return ps; +} + +pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, 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, 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(NULL, 0, 0); + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps, 0); + PCB_SET_PARENT(ps, data, data); +} + +void pcb_pstk_bbox(pcb_pstk_t *ps) +{ + 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); + + ps->BoundingBox.X1 = ps->BoundingBox.X2 = ps->x; + ps->BoundingBox.Y1 = ps->BoundingBox.Y2 = ps->y; + + 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(&ps->BoundingBox, 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(&ps->BoundingBox, &line.BoundingBox); + break; + case PCB_PSSH_CIRC: + pcb_box_bump_point(&ps->BoundingBox, ps->x - shape->data.circ.dia/2, ps->y - shape->data.circ.dia/2); + pcb_box_bump_point(&ps->BoundingBox, ps->x + shape->data.circ.dia/2, ps->y + shape->data.circ.dia/2); + break; + } + } + + if (PCB_NONPOLY_HAS_CLEARANCE(ps)) { + ps->BoundingBox.X1 -= ps->Clearance; + ps->BoundingBox.Y1 -= ps->Clearance; + ps->BoundingBox.X2 += ps->Clearance; + ps->BoundingBox.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(&ps->BoundingBox, ps->x - proto->hdia/2, ps->y - proto->hdia/2); + pcb_box_bump_point(&ps->BoundingBox, ps->x + proto->hdia/2, ps->y + proto->hdia/2); + } + + pcb_close_box(&ps->BoundingBox); +} + +/*** 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; +} + +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) +{ + char *color, *layer_color = NULL; + char buf[sizeof("#XXXXXX")]; + + if (lyt & PCB_LYT_PASTE) + layer_color = conf_core.appearance.color.paste; + + if (ps->term == NULL) { + /* normal via, not a terminal */ + if (!pcb_draw_doing_pinout && 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.via_selected; + else + color = conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, ps)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + } + else { + if (layer_color != NULL) + color = layer_color; + else if (is_current) + color = conf_core.appearance.color.via; + else + color = conf_core.appearance.color.invisible_objects; + } + } + else { + /* terminal */ + if (!pcb_draw_doing_pinout && 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.pin_selected; + else + color = conf_core.appearance.color.connected; + + if (PCB_FLAG_TEST(PCB_FLAG_ONPOINT, ps)) { + assert(color != NULL); + pcb_lighten_color(color, buf, 1.75); + color = buf; + } + } + else + if (layer_color != NULL) + color = layer_color; + else if (is_current) + color = conf_core.appearance.color.pin; + else + color = conf_core.appearance.color.invisible_objects; + + } + + 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.subc_selected : conf_core.appearance.color.padstackmark); +} + +static void pcb_pstk_draw_shape_solid(pcb_hid_gc_t gc, pcb_pstk_t *ps, pcb_pstk_shape_t *shape) +{ + switch(shape->shape) { + case PCB_PSSH_POLY: + pcb_gui->fill_polygon_offs(pcb_draw_out.fgGC, shape->data.poly.len, shape->data.poly.x, shape->data.poly.y, ps->x, ps->y); + break; + case PCB_PSSH_LINE: + pcb_gui->set_line_cap(pcb_draw_out.fgGC, shape->data.line.square ? Square_Cap : Round_Cap); + pcb_gui->set_line_width(pcb_draw_out.fgGC, shape->data.line.thickness); + pcb_gui->draw_line(pcb_draw_out.fgGC, 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: + pcb_gui->fill_circle(pcb_draw_out.fgGC, ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, shape->data.circ.dia/2); + break; + } +} + +static void pcb_pstk_draw_shape_thin(pcb_hid_gc_t gc, pcb_pstk_t *ps, pcb_pstk_shape_t *shape) +{ + int n; + switch(shape->shape) { + case PCB_PSSH_POLY: + 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]); + 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, shape->data.line.thickness, shape->data.line.square); + break; + case PCB_PSSH_CIRC: + pcb_gui->draw_arc(gc, ps->x + shape->data.circ.x, ps->y + shape->data.circ.y, shape->data.circ.dia/2, shape->data.circ.dia/2, 0, 360); + break; + } +} + +pcb_r_dir_t pcb_pstk_draw_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_draw_t *ctx = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_shape_t *shape; + pcb_layergrp_t *grp; + + if (!PCB->SubcPartsOn && pcb_gobj_parent_subc(ps->parent_type, &ps->parent)) + return PCB_R_DIR_NOT_FOUND; + + shape = pcb_pstk_shape_gid(ctx->pcb, ps, ctx->gid, ctx->comb, &grp); + if (shape != NULL) { + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 0); + set_ps_color(ps, ctx->is_current, grp->type); + if (conf_core.editor.thin_draw || conf_core.editor.wireframe_draw) { + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_pstk_draw_shape_thin(pcb_draw_out.fgGC, ps, shape); + } + else + pcb_pstk_draw_shape_solid(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; + + /* mark is a cross in the middle, right on the hole; + cross size should extend beyond the hole */ + mark = PS_CROSS_SIZE/2; + proto = pcb_pstk_get_proto(ps); + if (proto != NULL) + mark += proto->hdia/2; + + /* draw the cross using xor */ + set_ps_annot_color(pcb_draw_out.fgGC, ps); + pcb_gui->set_line_width(pcb_draw_out.fgGC, -3); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 1); + 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); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 0); + + /* draw the label if enabled, after everything else is drawn */ + if (ps->term != NULL) { + if ((pcb_draw_doing_pinout) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, ps)) + pcb_draw_delay_label_add((pcb_any_obj_t *)ps); + } + return PCB_R_DIR_FOUND_CONTINUE; +} + + +pcb_r_dir_t pcb_pstk_draw_hole_callback(const pcb_box_t *b, void *cl) +{ + pcb_pstk_draw_t *ctx = cl; + pcb_pstk_t *ps = (pcb_pstk_t *)b; + pcb_pstk_proto_t *proto; + + /* hide subc parts if requested */ + if (!PCB->SubcPartsOn && pcb_gobj_parent_subc(ps->parent_type, &ps->parent)) + return PCB_R_DIR_NOT_FOUND; + + /* no hole in this layer group */ + if (!pcb_pstk_bb_drills(ctx->pcb, ps, ctx->gid, &proto)) + return PCB_R_DIR_FOUND_CONTINUE; + + /* No hole at all */ + if (proto->hdia <= 0) + return PCB_R_DIR_NOT_FOUND; + + /* hole is plated, but the caller doesn't want plated holes */ + if (proto->hplated && (!(ctx->holetype & PCB_PHOLE_PLATED))) + return PCB_R_DIR_NOT_FOUND; + + /* hole is unplated, but the caller doesn't want unplated holes */ + if (!proto->hplated && (!(ctx->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)) && (!(ctx->holetype & PCB_PHOLE_BB))) + return PCB_R_DIR_NOT_FOUND; + + /* actual hole */ + 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.subc_selected : conf_core.appearance.color.subc); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 1); + pcb_gui->draw_arc(pcb_draw_out.fgGC, ps->x, ps->y, r, r, 20, 290); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 0); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +void pcb_pstk_thindraw(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) + shape = ts->shape; + } + + if (shape != NULL) { + pcb_gui->set_draw_xor(gc, 0); + pcb_pstk_draw_shape_thin(gc, ps, shape); + } +} + +void pcb_pstk_draw_label(pcb_pstk_t *ps) +{ + pcb_coord_t offs = 0; + pcb_pstk_proto_t *proto; + + if (ps->term == NULL) + return; + + proto = pcb_pstk_get_proto(ps); + if ((proto != NULL) && (proto->hdia > 0)) + offs = proto->hdia/2; + pcb_term_label_draw(ps->x + offs, ps->y, 100.0, 0, pcb_false, ps->term, ps->intconn); +} + + +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_pad_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_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; +} + +int pcb_pstk_near_box(pcb_pstk_t *ps, pcb_box_t *box, pcb_layer_t *layer) +{ + pcb_pstk_shape_t *shp; + + /* no layer means: "is any shape near?" */ + 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_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_pad_t pad; + pcb_vector_t v; + 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; + } + + switch(shape->shape) { + 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_pad(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; + + /* 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 * PCB->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 * PCB->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, pcb_coord_t *out) +{ + double dist, neck, mindist2, dist2; + pcb_line_t line; + int n; + + switch(shp->shape) { + case PCB_PSSH_CIRC: + dist = sqrt(shp->data.circ.x*shp->data.circ.x + shp->data.circ.y*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 = shp->data.poly.x[n] * shp->data.poly.x[n] + shp->data.poly.y[n] * 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 = sqrt(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 (pcb_pstk_shape_hole_break(&ts->shape[n], proto->hdia, 2 * PCB->minRing, err_minring)) { + break; + } + } + } + + if ((proto->hdia > 0) && (proto->hdia < PCB->minDrill)) + *err_minhole = proto->hdia; +} + +void pcb_pstk_mirror(pcb_pstk_t *ps, pcb_coord_t y_offs, int swap_side) +{ + int xmirror = !ps->xmirror, smirror = (swap_side ? (!ps->smirror) : ps->smirror); + + /* change the mirror flag - this will automatically cause mirroring in + every aspect */ + 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) { + pcb_poly_restore_to_poly(ps->parent.data, PCB_TYPE_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; + if ((swap_side) && (ps->rot != 0)) + ps->rot = -ps->rot; + pcb_pstk_bbox(ps); + + if (ps->parent.data->padstack_tree != NULL) + pcb_r_insert_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps, 0); + pcb_poly_clear_from_poly(ps->parent.data, PCB_TYPE_PSTK, NULL, ps); + pcb_pstk_invalidate_draw(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_TYPE_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, 0); + pcb_poly_clear_from_poly(ps->parent.data, PCB_TYPE_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; + + 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; + 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" Index: tags/1.2.7/src/obj_pstk.h =================================================================== --- tags/1.2.7/src/obj_pstk.h (nonexistent) +++ tags/1.2.7/src/obj_pstk.h (revision 13657) @@ -0,0 +1,189 @@ +/* + * 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. + * + */ + +#ifndef PCB_OBJ_PSTK_STRUCT_DECLARED +#define PCB_OBJ_PSTK_STRUCT_DECLARED + +#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_ANYOBJECTFIELDS; +#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 */ + 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; +} pcb_pstk_proto_t; + + + +pcb_pstk_t *pcb_pstk_alloc(pcb_data_t *data); +void pcb_pstk_free(pcb_pstk_t *ps); +pcb_pstk_t *pcb_pstk_new(pcb_data_t *data, 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, 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_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); + + +/*** 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); + +/* 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); + +/* 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. */ +pcb_cardinal_t pcb_pstk_proto_insert_dup(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); + +/* 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); + +/* 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); + +/* 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); + +/* Mirror a padstack (useful for sending to the other side - set swap_side to 1 in that case) */ +void pcb_pstk_mirror(pcb_pstk_t *ps, pcb_coord_t y_offs, int swap_side); + +/* 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; + + +/*** hash ***/ +unsigned int pcb_pstk_hash(const pcb_pstk_proto_t *p); +int pcb_pstk_eq(const pcb_pstk_proto_t *p1, const pcb_pstk_proto_t *p2); + +/*** 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/1.2.7/src/obj_pstk_act.c =================================================================== --- tags/1.2.7/src/obj_pstk_act.c (nonexistent) +++ tags/1.2.7/src/obj_pstk_act.c (revision 13657) @@ -0,0 +1,154 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" + +#include "action_helper.h" +#include "board.h" +#include "conf_core.h" +#include "data.h" +#include "hid_actions.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"; + +int pcb_act_padstackconvert(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_cardinal_t pid; + pcb_pstk_proto_t tmp, *p; + + if (argv[0] == NULL) + PCB_ACT_FAIL(padstackconvert); + if (strcmp(argv[0], "selected") == 0) { + if (argc > 2) { + pcb_bool s1, s2; + x = pcb_get_value(argv[1], "mil", NULL, &s1); + y = pcb_get_value(argv[2], "mil", NULL, &s2); + if (!s1 || !s2) { + pcb_message(PCB_MSG_ERROR, "Error in coordinate format\n"); + return -1; + } + } + else { + pcb_gui->get_coords("Click at padstack origin", &x, &y); + /* 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... */ + } + } + else if (strcmp(argv[0], "buffer") == 0) { + + 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... */ + } + } + else + 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, 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); + + 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)"; + +int pcb_act_padstackplace(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_cardinal_t pid; + pcb_pstk_t *ps; + + if (argc > 2) { + pcb_bool s1, s2; + x = pcb_get_value(argv[1], "mil", NULL, &s1); + y = pcb_get_value(argv[2], "mil", NULL, &s2); + if (!s1 || !s2) { + pcb_message(PCB_MSG_ERROR, "Error in coordinate format\n"); + return -1; + } + } + + if ((argc <= 0) || (strcmp(argv[0], "default") == 0)) { +#warning padstack TODO: style default proto + pid = 0; + } + else { + char *end; + pid = strtol(argv[0], &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, 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; + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +pcb_hid_action_t padstack_action_list[] = { + {"PadstackConvert", 0, pcb_act_padstackconvert, + pcb_acth_padstackconvert, pcb_acts_padstackconvert}, + {"PadstackPlace", 0, pcb_act_padstackplace, + pcb_acth_padstackplace, pcb_acts_padstackplace} +}; + +PCB_REGISTER_ACTIONS(padstack_action_list, NULL) Index: tags/1.2.7/src/obj_pstk_draw.h =================================================================== --- tags/1.2.7/src/obj_pstk_draw.h (nonexistent) +++ tags/1.2.7/src/obj_pstk_draw.h (revision 13657) @@ -0,0 +1,61 @@ +/* + * 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. + * + */ + +#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 "layer_grp.h" + +typedef enum { + PCB_PHOLE_PLATED = 1, + PCB_PHOLE_UNPLATED = 2, + PCB_PHOLE_BB = 4 +} pcb_pstk_draw_hole_t; + +typedef struct { + pcb_board_t *pcb; + pcb_layergrp_id_t gid; + int is_current; + pcb_pstk_draw_hole_t holetype; + pcb_layer_combining_t comb; +} pcb_pstk_draw_t; + +pcb_r_dir_t pcb_pstk_draw_callback(const pcb_box_t *b, void *cl); +pcb_r_dir_t pcb_pstk_clear_callback(const pcb_box_t *b, void *cl); +#endif + +void pcb_pstk_draw(pcb_pstk_t *ps, pcb_bool draw_hole); +pcb_r_dir_t pcb_pstk_draw_mark_callback(const pcb_box_t *b, void *cl); +void pcb_pstk_draw_label(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_hid_gc_t gc, pcb_pstk_t *ps); + + +#endif Index: tags/1.2.7/src/obj_pstk_inlines.h =================================================================== --- tags/1.2.7/src/obj_pstk_inlines.h (nonexistent) +++ tags/1.2.7/src/obj_pstk_inlines.h (revision 13657) @@ -0,0 +1,265 @@ +/* + * 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. + * + */ + +#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(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(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, 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 (proto->hdia == 0) { + 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 (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, 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; +} + +PCB_INLINE pcb_pstk_shape_t *pcb_pstk_shape_at(pcb_board_t *pcb, pcb_pstk_t *ps, pcb_layer_t *layer) +{ + 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 */ + layer = pcb_layer_get_real(layer); + if ((layer != NULL) && (layer->parent != NULL)) { + lid = pcb_layer_id(layer->parent, 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_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->type & PCB_LYT_COPPER) { + int n, nosh; + + /* blind/buried: intern layer has no shape if no hole */ + if (grp->type & 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->type, comb); +} + + +#endif Index: tags/1.2.7/src/obj_pstk_list.c =================================================================== --- tags/1.2.7/src/obj_pstk_list.c (nonexistent) +++ tags/1.2.7/src/obj_pstk_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_pstk_list.h" +#include Index: tags/1.2.7/src/obj_pstk_list.h =================================================================== --- tags/1.2.7/src/obj_pstk_list.h (nonexistent) +++ tags/1.2.7/src/obj_pstk_list.h (revision 13657) @@ -0,0 +1,47 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_pstk_op.c =================================================================== --- tags/1.2.7/src/obj_pstk_op.c (nonexistent) +++ tags/1.2.7/src/obj_pstk_op.c (revision 13657) @@ -0,0 +1,326 @@ +/* + * 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. + * + */ + +#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, 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); +} + +void *pcb_pstkop_move_to_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_TYPE_PSTK, NULL, ps); + pcb_r_delete_entry(ctx->buffer.src->padstack_tree, (pcb_box_t *)ps); + + padstacklist_remove(ps); + ps->proto = npid; + ps->protoi = -1; /* only the canonical trshape got copied, not the transofrmed ones */ + padstacklist_append(&ctx->buffer.dst->padstack, 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(NULL, 0, 0); + + pcb_r_insert_entry(ctx->buffer.dst->padstack_tree, (pcb_box_t *)ps, 0); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_PSTK, NULL, ps); + + PCB_SET_PARENT(ps, data, ctx->buffer.dst); + 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, 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_TYPE_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); + pcb_draw(); + 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_TYPE_PSTK, NULL, ps); + pcb_pstkop_move_noclip(ctx, ps); + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_PSTK, NULL, 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_TYPE_PSTK, NULL, ps); + } + if (ctx->clip.clear) { + if (data->padstack_tree != NULL) + pcb_r_insert_entry(data->padstack_tree, (pcb_box_t *)ps, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_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_TYPE_PSTK, ps, ps, 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_TYPE_PSTK, ps, ps, ps, pcb_false); + pcb_poly_restore_to_poly(pcb->Data, PCB_TYPE_PSTK, layer, ps); + +#warning TODO: undo + pcb_pstk_set_thermal(ps, ctx->chgtherm.lid, ctx->chgtherm.style); + + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_PSTK, ps, ps, ps, pcb_true); + pcb_poly_clear_from_poly(pcb->Data, PCB_TYPE_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_FLAG_TEST(PCB_FLAG_LOCK, ps)) + return NULL; + + if (pcb_pstk_flags == 0) + pcb_pstk_flags = pcb_obj_valid_flags(PCB_TYPE_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; + + 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_TYPE_PSTK, NULL, ps); + pcb_pstk_invalidate_erase(ps); + 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); + pcb_r_insert_entry(ps->parent.data->padstack_tree, (pcb_box_t *)ps, 0); + pcb_poly_clear_from_poly(ps->parent.data, PCB_TYPE_PSTK, NULL, ps); + pcb_pstk_invalidate_draw(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) + 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 : ps->Clearance + ctx->chgsize.value; + + 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 < PCB->Bloat * 2)) + value = 0; + if ((ctx->chgsize.value > 0) && (value < PCB->Bloat * 2)) + value = PCB->Bloat * 2 + 2; + if (ps->Clearance == value) + return NULL; + + if (pcb_pstk_change_instance(ps, NULL, &value, NULL, NULL, NULL) == 0) + 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 < ctx->chgsize.pcb->minDrill) + proto.hdia = ctx->chgsize.pcb->minDrill; + } + 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) + return ps; + + return NULL; +} + Index: tags/1.2.7/src/obj_pstk_op.h =================================================================== --- tags/1.2.7/src/obj_pstk_op.h (nonexistent) +++ tags/1.2.7/src/obj_pstk_op.h (revision 13657) @@ -0,0 +1,50 @@ +/* + * 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. + * + */ + +/*** 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_to_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/1.2.7/src/obj_pstk_proto.c =================================================================== --- tags/1.2.7/src/obj_pstk_proto.c (nonexistent) +++ tags/1.2.7/src/obj_pstk_proto.c (revision 13657) @@ -0,0 +1,893 @@ +/* + * 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. + * + */ + +#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" + +static const char core_proto_cookie[] = "padstack prototypes"; + + +void pcb_pstk_proto_free_fields(pcb_pstk_proto_t *dst) +{ +#warning TODO: do a full field free here +} + +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; +} + +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 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; + pcb_any_obj_t **o; + pcb_pstk_tshape_t *ts; + pcb_pin_t *via = NULL; + + dst->in_use = 1; + pcb_vtpadstack_tshape_init(&dst->tr); + dst->hdia = 0; + dst->htop = dst->hbottom = 0; + + if (vtp0_len(objs) > data->LayerN) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: too many objects selected\n"); + goto quit; + } + + /* 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++) { + switch((*o)->type) { + case PCB_OBJ_LINE: + case PCB_OBJ_POLY: + ts->len++; + break; + case PCB_OBJ_VIA: + if (via != NULL) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: multiple vias\n"); + goto quit; + } + via = *(pcb_pin_t **)o; + dst->hdia = via->DrillingHole; + dst->hplated = !PCB_FLAG_TEST(PCB_FLAG_HOLE, *o); + if ((ox != via->X) || (oy != via->Y)) { + pcb_message(PCB_MSG_INFO, "Padstack conversion: adjusting origin to via hole\n"); + ox = via->X; + oy = via->Y; + } + break; + default:; + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: invalid object type (%x) selected; must be via, line or polygon\n", (*o)->type); + goto quit; + } + } + + if ((ts->len == 0) && (via == NULL)) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: there are no shapes and there is no via 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; + + 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) && (via == NULL)) { + if (!quiet) + pcb_message(PCB_MSG_ERROR, "Padstack conversion: can not have internal copper shape if there is no hole\n"); + goto quit; + } + } + + /* if there was a via, use the via's shape on layers that are not specified */ + if (via != NULL) { + if (pcb_pstk_get_shape_idx(ts, PCB_LYT_COPPER | PCB_LYT_TOP, 0) == -1) + append_circle(ts, PCB_LYT_COPPER | PCB_LYT_TOP, 0, via->Thickness); + if (pcb_pstk_get_shape_idx(ts, PCB_LYT_COPPER | PCB_LYT_INTERN, 0) == -1) + append_circle(ts, PCB_LYT_COPPER | PCB_LYT_INTERN, 0, via->Thickness); + if (pcb_pstk_get_shape_idx(ts, PCB_LYT_COPPER | PCB_LYT_BOTTOM, 0) == -1) + append_circle(ts, PCB_LYT_COPPER | PCB_LYT_BOTTOM, 0, via->Thickness); + if (via->Mask > 0) { + if (pcb_pstk_get_shape_idx(ts, PCB_LYT_MASK | PCB_LYT_BOTTOM, PCB_LYC_SUB) == -1) + append_circle(ts, PCB_LYT_MASK | PCB_LYT_BOTTOM, PCB_LYC_SUB, via->Mask); + if (pcb_pstk_get_shape_idx(ts, PCB_LYT_MASK | PCB_LYT_TOP, PCB_LYC_SUB) == -1) + append_circle(ts, PCB_LYT_MASK | PCB_LYT_TOP, PCB_LYC_SUB, via->Mask); + } + } + + /* all went fine */ + dst->hash = pcb_pstk_hash(dst); + ret = 0; + + quit:; + if (ret != 0) + pcb_pstk_proto_free_fields(dst); + return ret; +} + +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, PCB_FLAGS); + 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: + 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: + 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: + 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_tshape_rot(pcb_pstk_tshape_t *ts, double angle) +{ + int n, i; + 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_t *sh = &ts->shape[n]; + 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_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_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_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); + + 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_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) { + n = pcb_vtpadstack_proto_len(&data->ps_protos); + pcb_vtpadstack_proto_append(&data->ps_protos, *proto); + } + else { + memcpy(data->ps_protos.array+first_free, proto, sizeof(pcb_pstk_proto_t)); + data->ps_protos.array[first_free].in_use = 1; + } + memset(proto, 0, sizeof(pcb_pstk_proto_t)); /* make sure a subsequent free() won't do any harm */ + return n; +} + +pcb_cardinal_t pcb_pstk_proto_insert_dup(pcb_data_t *data, const 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) + 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; + } + 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; + } + return n; +} + +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)) { + pcb_polyarea_free(&poly->pa); + + poly->pa = pcb_polyarea_create(); + pcb_poly_contour_inv(pl); + pcb_polyarea_contour_include(poly->pa, pl); + } + +} + +/*** 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; +} + +#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; + + 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_POLY: + pcb_pstk_poly_center(&shp->data.poly, &cx, &cy); + pcb_polyarea_free(&shp->data.poly.pa); + if (is_absolute) { +#warning TODO + } + else { + /* relative: move each point radially */ + for(n = 0; n < shp->data.poly.len; n++) { + double dx = shp->data.poly.x[n] - cx, dy = shp->data.poly.y[n] - cy; + double dist = sqrt(dx*dx + dy*dy); + double vx = dx / dist, vy = dy / dist; + dist += val; + if (dist <= PCB_MM_TO_COORD(0.01)) + dist = PCB_MM_TO_COORD(0.01); + shp->data.poly.x[n] = cx + vx * dist; + shp->data.poly.y[n] = cy + vy * dist; + } + } + pcb_pstk_shape_update_pa(&shp->data.poly); + break; + } +} + +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); +} + +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); + } +} + + +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); +} + +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); +} + + +/*** 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; + } + + return ret; +} + +unsigned int pcb_pstk_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) ^ pcb_hash_coord(ts->len); + for(n = 0; n < ts->len; n++) + ret ^= pcb_pstk_shape_hash(ts->shape + n); + return ret; +} + +static 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; + } + + return 1; +} + +int pcb_pstk_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->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/1.2.7/src/obj_pstk_shape.h =================================================================== --- tags/1.2.7/src/obj_pstk_shape.h (nonexistent) +++ tags/1.2.7/src/obj_pstk_shape.h (revision 13657) @@ -0,0 +1,73 @@ +/* + * 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. + * + */ + +#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, X coord */ + pcb_polyarea_t *pa; /* cache for the poly code */ +} 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 */ + } 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; + +#endif Index: tags/1.2.7/src/obj_rat.c =================================================================== --- tags/1.2.7/src/obj_rat.c (nonexistent) +++ tags/1.2.7/src/obj_rat.c (revision 13657) @@ -0,0 +1,291 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: pins and vias */ + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "undo.h" +#include "rtree.h" + +#include "obj_line_draw.h" + +#include "obj_rat.h" +#include "obj_rat_list.h" +#include "obj_rat_op.h" + + + +/* TODO: consider moving the code from draw.c here and remove this: */ +#include "draw.h" +#include "obj_rat_draw.h" + +/* TODO: merge rats.[ch] too */ +#include "rats.h" + +/*** allocation ***/ +/* get next slot for a Rat, allocates memory if necessary */ +pcb_rat_t *pcb_rat_alloc(pcb_data_t *data) +{ + pcb_rat_t *new_obj; + + new_obj = calloc(sizeof(pcb_rat_t), 1); + new_obj->type = PCB_OBJ_RAT; + PCB_SET_PARENT(new_obj, data, data); + + ratlist_append(&data->Rat, new_obj); + + return new_obj; +} + +void pcb_rat_free(pcb_rat_t *data) +{ + ratlist_remove(data); + free(data); +} + +/*** utility ***/ +/* creates a new rat-line */ +pcb_rat_t *pcb_rat_new(pcb_data_t *Data, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_cardinal_t group1, pcb_cardinal_t group2, pcb_coord_t Thickness, pcb_flag_t Flags) +{ + pcb_rat_t *Line = pcb_rat_alloc(Data); + + if (!Line) + return (Line); + + Line->ID = pcb_create_ID_get(); + 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(NULL, 0, 0); + pcb_r_insert_entry(Data->rat_tree, &Line->BoundingBox, 0); + 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.bulk = pcb_true; + 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_draw(); + pcb_undo_inc_serial(); + } + return (changed); +} + + +/*** ops ***/ +/* copies a rat-line to paste buffer */ +void *pcb_ratop_add_to_buffer(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + return (pcb_rat_new(ctx->buffer.dst, 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))); +} + +/* moves a rat-line to paste buffer */ +void *pcb_ratop_move_to_buffer(pcb_opctx_t *ctx, pcb_rat_t * rat) +{ + pcb_r_delete_entry(ctx->buffer.src->rat_tree, (pcb_box_t *) rat); + + ratlist_remove(rat); + ratlist_append(&ctx->buffer.dst->Rat, rat); + + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, rat); + + if (!ctx->buffer.dst->rat_tree) + ctx->buffer.dst->rat_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(ctx->buffer.dst->rat_tree, (pcb_box_t *) rat, 0); + + PCB_SET_PARENT(rat, data, ctx->buffer.dst); + + 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_TYPE_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_TYPE_LINE, CURRENT, newone, newone); + pcb_line_invalidate_draw(CURRENT, newone); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_RATLINE, Rat, Rat, Rat); + pcb_draw(); + 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_TYPE_LINE, ctx->move.dst_layer, newone, newone); + if (PCB->RatOn) + pcb_rat_invalidate_erase(Rat); + pcb_undo_move_obj_to_remove(PCB_TYPE_RATLINE, Rat, Rat, Rat); + pcb_line_invalidate_draw(ctx->move.dst_layer, newone); + pcb_draw(); + 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); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_RATLINE, 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.rat_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_gui->set_line_width(pcb_draw_out.fgGC, 0); + else + pcb_gui->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_((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); +} Index: tags/1.2.7/src/obj_rat.h =================================================================== --- tags/1.2.7/src/obj_rat.h (nonexistent) +++ tags/1.2.7/src/obj_rat.h (revision 13657) @@ -0,0 +1,47 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: rats */ + +#ifndef PCB_OBJ_RAT_H +#define PCB_OBJ_RAT_H + +#include "obj_common.h" + +struct pcb_rat_line_s { /* a rat-line */ + PCB_ANYLINEFIELDS; + pcb_cardinal_t group1, group2; /* the layer group each point is on */ + gdl_elem_t link; /* an arc is in a list on a design */ +}; + + +pcb_rat_t *pcb_rat_alloc(pcb_data_t *data); +void pcb_rat_free(pcb_rat_t *data); + +pcb_rat_t *pcb_rat_new(pcb_data_t *Data, pcb_coord_t X1, pcb_coord_t Y1, pcb_coord_t X2, pcb_coord_t Y2, pcb_cardinal_t group1, pcb_cardinal_t group2, pcb_coord_t Thickness, pcb_flag_t Flags); +pcb_bool pcb_rats_destroy(pcb_bool selected); + +#endif Index: tags/1.2.7/src/obj_rat_draw.h =================================================================== --- tags/1.2.7/src/obj_rat_draw.h (nonexistent) +++ tags/1.2.7/src/obj_rat_draw.h (revision 13657) @@ -0,0 +1,35 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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/1.2.7/src/obj_rat_list.c =================================================================== --- tags/1.2.7/src/obj_rat_list.c (nonexistent) +++ tags/1.2.7/src/obj_rat_list.c (revision 13657) @@ -0,0 +1,25 @@ +/* + * 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. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_rat_list.h" +#include Index: tags/1.2.7/src/obj_rat_list.h =================================================================== --- tags/1.2.7/src/obj_rat_list.h (nonexistent) +++ tags/1.2.7/src/obj_rat_list.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_rat_op.h =================================================================== --- tags/1.2.7/src/obj_rat_op.h (nonexistent) +++ tags/1.2.7/src/obj_rat_op.h (revision 13657) @@ -0,0 +1,36 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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_to_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/1.2.7/src/obj_subc.c =================================================================== --- tags/1.2.7/src/obj_subc.c (nonexistent) +++ tags/1.2.7/src/obj_subc.c (revision 13657) @@ -0,0 +1,1572 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include + +#include "buffer.h" +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "error.h" +#include "obj_subc.h" +#include "obj_subc_op.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 "flag.h" +#include "polygon.h" +#include "operation.h" +#include "undo.h" +#include "compat_misc.h" +#include "math_helper.h" +#include "pcb_minuid.h" +#include "conf_core.h" + +#define SUBC_AUX_NAME "subc-aux" + +/* 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(void) +{ + pcb_subc_t *sc; + sc = calloc(sizeof(pcb_subc_t), 1); + 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; +} + +void pcb_subc_free(pcb_subc_t *sc) +{ + pcb_term_uninit(&sc->terminals); + pcb_subclist_remove(sc); + pcb_data_free(sc->data); + free(sc->data); + free(sc); +} + + +void pcb_add_subc_to_data(pcb_data_t *dt, pcb_subc_t *sc) +{ + PCB_SET_PARENT(sc->data, subc, sc); + PCB_SET_PARENT(sc, data, dt); + pcb_subclist_append(&dt->subc, 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 = sc->data; + 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; +} + +/* 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) { + 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; + break; + } + } + } + + 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; +} + +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) +{ + if ((pcb_subc_cache_update(sc) != 0) || (sc->aux_cache[PCB_SUBCH_X] == NULL)) + return -1; + + *rot = 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); + return 0; +} + +/* The subc is originally drawn on the top side, and teh 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; +} + +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, 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_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; + } + return layer; +} + +extern unsigned long pcb_obj_type2oldtype(pcb_objtype_t type); + +/* Move the pad-side-effect objects to the appropriate layer */ +static void move_pad_side_effect(pcb_any_obj_t *o, pcb_layer_t *top, pcb_layer_t *bottom) +{ + pcb_layer_t *source = o->parent.layer; + pcb_layer_t *target = (source->meta.bound.type & PCB_LYT_TOP) ? top : bottom; + switch(o->type) { + case PCB_OBJ_POLY: + pcb_polyop_move_to_layer_low(NULL, source, (pcb_poly_t *)o, target); + break; + case PCB_OBJ_LINE: + pcb_lineop_move_to_layer_low(NULL, source, (pcb_line_t *)o, target); + break; + default: + assert(!"internal error: invalid mask/paste side effect"); + } +} + +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; +} + +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(); + sc->ID = pcb_create_ID_get(); + pcb_add_subc_to_data(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 */ + linelist_remove(line); + linelist_append(&dst->Line, line); + PCB_SET_PARENT(line, layer, dst); + 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) { + arclist_remove(arc); + arclist_append(&dst->Arc, arc); + PCB_SET_PARENT(arc, layer, dst); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, arc); + } + + while((text = textlist_first(&src->Text)) != NULL) { + textlist_remove(text); + textlist_append(&dst->Text, text); + PCB_SET_PARENT(text, layer, dst); + 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) { + polylist_remove(poly); + polylist_append(&dst->Polygon, poly); + PCB_SET_PARENT(poly, layer, dst); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, poly); + } + } + + { /* check if we have pins - they need mask */ + pcb_pin_t *via; + + for(via = pinlist_first(&buffer->Data->Via); via != NULL; via = pinlist_next(via)) { + if (pcb_attribute_get(&via->Attributes, "elem_smash_pad") != NULL) { + top_pads++; + bottom_pads++; + break; + } + } + } + + /* 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"); + if (dst_top_mask == NULL) { + dst_top_mask = pcb_layer_new_bound(sc->data, PCB_LYT_TOP | PCB_LYT_MASK, "top mask"); + 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"); + if (dst_bottom_mask == NULL) { + dst_bottom_mask = pcb_layer_new_bound(sc->data, PCB_LYT_BOTTOM | PCB_LYT_MASK, "bottom mask"); + dst_bottom_mask->comb = PCB_LYC_SUB; + } + } + } + + { /* convert globals */ + pcb_pin_t *via; + pcb_pstk_t *ps; + + while((via = pinlist_first(&buffer->Data->Via)) != NULL) { + const char *term; + pinlist_remove(via); + pinlist_append(&sc->data->Via, via); + PCB_SET_PARENT(via, data, sc->data); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, via); + term = pcb_attribute_get(&via->Attributes, "term"); + if (pcb_attribute_get(&via->Attributes, "elem_smash_pad") != NULL) { + pcb_coord_t mask = read_mask((pcb_any_obj_t *)via); + + if (mask == 0) + mask = via->Mask; + + if (mask > 0) { + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, via)) { + pcb_line_t line; + pcb_poly_t *poly; + memset(&line, 0, sizeof(line)); + line.Point1.X = line.Point2.X = via->X; + line.Point1.Y = line.Point2.Y = via->Y; + line.Thickness = mask; + poly = sqline2term(dst_top_mask, &line); + if (term != NULL) + pcb_attribute_put(&poly->Attributes, "term", term); + poly = sqline2term(dst_bottom_mask, &line); + if (term != NULL) + pcb_attribute_put(&poly->Attributes, "term", term); + } + else { + pcb_line_t *line; + line = pcb_line_new(dst_top_mask, via->X, via->Y, via->X, via->Y, mask, 0, pcb_no_flags()); + if (term != NULL) + pcb_attribute_put(&line->Attributes, "term", term); + line = pcb_line_new(dst_bottom_mask, via->X, via->Y, via->X, via->Y, mask, 0, pcb_no_flags()); + if (term != NULL) + pcb_attribute_put(&line->Attributes, "term", term); + } + } + } + } + + while((ps = padstacklist_first(&buffer->Data->padstack)) != NULL) { + const pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + padstacklist_remove(ps); + padstacklist_append(&sc->data->padstack, ps); + PCB_SET_PARENT(ps, data, sc->data); + 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; + } + } + + for(n = 0; n < vtp0_len(&paste_pads); n++) + move_pad_side_effect(paste_pads.array[n], dst_top_paste, dst_bottom_paste); + for(n = 0; n < vtp0_len(&mask_pads); n++) + move_pad_side_effect(mask_pads.array[n], dst_top_mask, dst_bottom_mask); + + vtp0_uninit(&mask_pads); + vtp0_uninit(&paste_pads); + + /* create aux layer */ + { + pcb_coord_t unit = PCB_MM_TO_COORD(1); + pcb_layer_t *aux = pcb_layer_new_bound(sc->data, PCB_LYT_VIRTUAL | PCB_LYT_NOEXPORT | PCB_LYT_MISC | PCB_LYT_TOP, SUBC_AUX_NAME); + + add_aux_line(aux, "subc-role", "origin", buffer->X, buffer->Y, buffer->X, buffer->Y); + add_aux_line(aux, "subc-role", "x", buffer->X, buffer->Y, buffer->X+unit, buffer->Y); + add_aux_line(aux, "subc-role", "y", buffer->X, buffer->Y, buffer->X, buffer->Y+unit); + } + + /* Add refdes */ + pcb_attribute_put(&sc->Attributes, "refdes", "U0"); + 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"); + if (dst_top_silk != NULL) + pcb_text_new(dst_top_silk, pcb_font(PCB, 0, 0), buffer->X, buffer->Y, 0, 100, "%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_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(pcb_crosshair.GC, DX - PCB_EMARK_SIZE, DY, DX, DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, DX + PCB_EMARK_SIZE, DY, DX, DY - PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, DX - PCB_EMARK_SIZE, DY, DX, DY + PCB_EMARK_SIZE); + pcb_gui->draw_line(pcb_crosshair.GC, DX + PCB_EMARK_SIZE, DY, DX, DY + PCB_EMARK_SIZE); +} + +void XORDrawSubc(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_gui->draw_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)); + + arclist_foreach(&ly->Arc, &it, arc) { + 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); + } + + polylist_foreach(&ly->Polygon, &it, poly) + XORPolygon_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); + 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_pin_t *via; + pcb_pstk_t *ps; + gdl_iterator_t it; + + pinlist_foreach(&sc->data->Via, &it, via) { + pcb_coord_t ox, oy; + ox = via->X; + oy = via->Y; + via->X = PCB_CSWAP_X(via->X, w, mirr); + via->Y = PCB_CSWAP_Y(via->Y, h, mirr); + via->X += DX; + via->Y += DY; + pcb_gui->thindraw_pcb_pv(pcb_crosshair.GC, pcb_crosshair.GC, via, pcb_true, pcb_false); + via->X = ox; + via->Y = oy; + } + 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(pcb_crosshair.GC, ps); + ps->x = ox; + ps->y = oy; + ps->xmirror = oxm; + ps->protoi = pri; + } + } + + pcb_subc_draw_origin(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_SET_PARENT(sc->data, subc, sc); + PCB_SET_PARENT(sc, data, dst); + pcb_subclist_append(&dst->subc, 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; + + /* 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; + 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 subcricuit 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); + pcb_box_bump_box_noflt(&sc->BoundingBox, &nline->BoundingBox); + } + } + + 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); + pcb_box_bump_box_noflt(&sc->BoundingBox, &narc->BoundingBox); + } + } + + 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); + pcb_box_bump_box_noflt(&sc->BoundingBox, &ntext->BoundingBox); + } + } + + } + 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->via_tree == NULL) + pcb->Data->via_tree = pcb_r_create_tree(NULL, 0, 0); + sc->data->via_tree = pcb->Data->via_tree; + if (pcb->Data->padstack_tree == NULL) + pcb->Data->padstack_tree = pcb_r_create_tree(NULL, 0, 0); + sc->data->padstack_tree = pcb->Data->padstack_tree; + } + + { /* make a copy of global data */ + pcb_pin_t *via, *nvia; + pcb_pstk_t *ps, *nps; + gdl_iterator_t it; + + pinlist_foreach(&src->data->Via, &it, via) { + nvia = pcb_via_dup_at(sc->data, via, dx, dy); + MAYBE_KEEP_ID(nvia, via); + if (nvia != NULL) + pcb_box_bump_box_noflt(&sc->BoundingBox, &nvia->BoundingBox); + } + + 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, 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) + pcb_box_bump_box_noflt(&sc->BoundingBox, &nps->BoundingBox); + } + } + + /* 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); + pcb_box_bump_box_noflt(&sc->BoundingBox, &npoly->BoundingBox); + pcb_poly_ppclear(npoly); + } + } + } + + memcpy(&sc->Flags, &src->Flags, sizeof(sc->Flags)); + + pcb_close_box(&sc->BoundingBox); + + if (pcb != NULL) { + if (!dst->subc_tree) + dst->subc_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(dst->subc_tree, (pcb_box_t *)sc, 0); + } + + 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); +} + + +/* 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) +{ + int n; + + sc->BoundingBox.X1 = sc->BoundingBox.Y1 = PCB_MAX_COORD; + sc->BoundingBox.X2 = sc->BoundingBox.Y2 = -PCB_MAX_COORD; + + 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(NULL, 0, 0); + } + + /* 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_TYPE_LINE, sl, line, line); + pcb_box_bump_box_noflt(&sc->BoundingBox, &line->BoundingBox); + } + + arclist_foreach(&sl->Arc, &it, arc) { + pcb_object_operation(opfunc, ctx, PCB_TYPE_ARC, sl, arc, arc); + pcb_box_bump_box_noflt(&sc->BoundingBox, &arc->BoundingBox); + } + + textlist_foreach(&sl->Text, &it, text) { + pcb_object_operation(opfunc, ctx, PCB_TYPE_TEXT, sl, text, text); + pcb_box_bump_box_noflt(&sc->BoundingBox, &text->BoundingBox); + } + + polylist_foreach(&sl->Polygon, &it, poly) { + pcb_object_operation(opfunc, ctx, PCB_TYPE_POLY, sl, poly, poly); + pcb_box_bump_box_noflt(&sc->BoundingBox, &poly->BoundingBox); + } + + } + + + /* execute on globals */ + { + pcb_pin_t *via; + pcb_pstk_t *ps; + gdl_iterator_t it; + + pinlist_foreach(&sc->data->Via, &it, via) { + pcb_object_operation(opfunc, ctx, PCB_TYPE_VIA, via, via, via); + pcb_box_bump_box_noflt(&sc->BoundingBox, &via->BoundingBox); + } + + padstacklist_foreach(&sc->data->padstack, &it, ps) { + pcb_object_operation(opfunc, ctx, PCB_TYPE_PSTK, ps, ps, ps); + pcb_box_bump_box_noflt(&sc->BoundingBox, &ps->BoundingBox); + } + } + + pcb_close_box(&sc->BoundingBox); + if (pcb_data_get_top(Data) != NULL) + pcb_r_insert_entry(Data->subc_tree, (pcb_box_t *)sc, 0); + DrawSubc(sc); + 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_TYPE_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(); + 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; +extern pcb_opfunc_t ChangeOctagonFunctions, SetOctagonFunctions, ClrOctagonFunctions; +extern pcb_opfunc_t ChangeSquareFunctions, SetSquareFunctions, ClrSquareFunctions; + +/* 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); + + /* do the move without messing with the clipping */ + pcb_subc_op(data, sc, &MoveFunctions_noclip, ctx); + + /* 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); + 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); +} + +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); +} + +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_rotate(&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->PinOn && 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; + + linelist_foreach(&sl->Line, &it, line) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_TYPE_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, 0); + chg++; + } + } + + arclist_foreach(&sl->Arc, &it, arc) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_TYPE_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, 0); + chg++; + } + } + + textlist_foreach(&sl->Text, &it, text) { + if (src_has_real_layer) { + pcb_poly_restore_to_poly(src_data, PCB_TYPE_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, 0); + chg++; + } + } + + 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, 0); + chg++; + } + if (dst_is_pcb) + pcb_poly_ppclear(poly); + } + + 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; +} + +void *pcb_subcop_move_to_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)); + + EraseSubc(sc); + + /* move the subc */ + if ((ctx->buffer.pcb != NULL) && (ctx->buffer.pcb->Data->subc_tree != NULL)) + pcb_r_delete_entry(ctx->buffer.pcb->Data->subc_tree, (pcb_box_t *)sc); + + pcb_subclist_remove(sc); + pcb_subclist_append(&ctx->buffer.dst->subc, sc); + + if (dst_is_pcb) { + if (ctx->buffer.dst->subc_tree == NULL) + ctx->buffer.dst->subc_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(ctx->buffer.dst->subc_tree, (pcb_box_t *)sc, 0); + } + + /* 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(NULL, 0, 0); + if (sl->arc_tree == NULL) sl->arc_tree = pcb_r_create_tree(NULL, 0, 0); + if (sl->text_tree == NULL) sl->text_tree = pcb_r_create_tree(NULL, 0, 0); + if (sl->polygon_tree == NULL) sl->polygon_tree = pcb_r_create_tree(NULL, 0, 0); + 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); + } + + /* move globals */ + { + pcb_pin_t *via; + pcb_pstk_t *ps; + gdl_iterator_t it; + + pinlist_foreach(&sc->data->Via, &it, via) { + if (sc->data->via_tree != NULL) + pcb_r_delete_entry(sc->data->via_tree, (pcb_box_t *)via); + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, via); + if (ctx->buffer.dst->via_tree != NULL) + pcb_r_insert_entry(ctx->buffer.dst->via_tree, (pcb_box_t *)via, 0); + } + + padstacklist_foreach(&sc->data->padstack, &it, ps) { + const pcb_pstk_proto_t *proto = pcb_pstk_get_proto(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 (ctx->buffer.dst->padstack_tree != NULL) + pcb_r_insert_entry(ctx->buffer.dst->padstack_tree, (pcb_box_t *)ps, 0); + ps->proto = pcb_pstk_proto_insert_dup(ctx->buffer.dst, proto, 1); + ps->protoi = -1; + } + } + + /* bind globals */ + if (dst_is_pcb) { + if (ctx->buffer.dst->via_tree == NULL) + ctx->buffer.dst->via_tree = pcb_r_create_tree(NULL, 0, 0); + sc->data->via_tree = ctx->buffer.dst->via_tree; + + if (ctx->buffer.dst->padstack_tree == NULL) + ctx->buffer.dst->padstack_tree = pcb_r_create_tree(NULL, 0, 0); + sc->data->padstack_tree = ctx->buffer.dst->padstack_tree; + } + else { + sc->data->via_tree = NULL; + sc->data->padstack_tree = NULL; + } + + PCB_FLAG_CLEAR(PCB_FLAG_WARN | PCB_FLAG_FOUND | PCB_FLAG_SELECTED, sc); + PCB_SET_PARENT(sc, data, ctx->buffer.dst); + 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_subc_select(NULL, nsc, PCB_CHGFLG_CLEAR, 0); + return nsc; +} + +/* break buffer subc into pieces */ +pcb_bool pcb_subc_smash_buffer(pcb_buffer_t *buff) +{ + pcb_subc_t *subc; + + if (pcb_subclist_length(&buff->Data->subc) != 1) + return (pcb_false); + + subc = pcb_subclist_first(&buff->Data->subc); + pcb_subclist_remove(subc); + + pcb_data_free(buff->Data); + buff->Data = subc->data; + buff->Data->parent_type = PCB_PARENT_INVALID; + buff->Data->parent.data = NULL; + + 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(NULL, 0, 0); + if (dl->arc_tree == NULL) dl->arc_tree = pcb_r_create_tree(NULL, 0, 0); + if (dl->text_tree == NULL) dl->text_tree = pcb_r_create_tree(NULL, 0, 0); + if (dl->polygon_tree == NULL) dl->polygon_tree = pcb_r_create_tree(NULL, 0, 0); + } + + 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_subcop_change_size(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ChangeSizeFunctions, ctx); + 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); + 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); + 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); + return sc; +} + +void *pcb_subcop_change_nonetlist(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ +#warning subc TODO: 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) +{ + pcb_attribute_put(&sc->Attributes, "refdes", ctx->chgname.new_name); + return sc; +} + +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); + + pcb_subclist_remove(sc); + EraseSubc(sc); + pcb_subc_free(sc); + return NULL; +} + +void *pcb_subcop_remove(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + EraseSubc(sc); + if (!ctx->remove.bulk) + pcb_draw(); + pcb_undo_move_obj_to_remove(PCB_TYPE_SUBC, sc, sc, sc); + return NULL; +} + +void *pcb_subc_remove(pcb_subc_t *sc) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; +/* PCB_CLEAR_PARENT(subc);*/ + + return pcb_subcop_remove(&ctx, sc); +} + + +void *pcb_subcop_clear_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ClrOctagonFunctions, ctx); + return sc; +} + +void *pcb_subcop_set_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &SetOctagonFunctions, ctx); + return sc; +} + +void *pcb_subcop_change_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ChangeOctagonFunctions, ctx); + return sc; +} + +void *pcb_subcop_clear_square(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ClrSquareFunctions, ctx); + return sc; +} + +void *pcb_subcop_set_square(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &SetSquareFunctions, ctx); + return sc; +} + +void *pcb_subcop_change_square(pcb_opctx_t *ctx, pcb_subc_t *sc) +{ + pcb_subc_op(ctx->chgsize.pcb->Data, sc, &ChangeSquareFunctions, ctx); + return sc; +} + + + +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_TYPE_SUBC); + + if (ctx->chgflag.flag == PCB_FLAG_FLOATER) { +#warning subc TODO: 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); + 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_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_data_mirror(subc->data, y_offs, smirror, smirror); + pcb_subc_bbox(subc); + + if ((data != NULL) && (data->subc_tree != NULL)) + pcb_r_insert_entry(data->subc_tree, (pcb_box_t *)subc, 0); +} + +pcb_bool pcb_subc_change_side(pcb_subc_t **subc, pcb_coord_t yoff) +{ + pcb_opctx_t ctx; + pcb_subc_t *newsc, *newsc2; + int n; + pcb_board_t *pcb; + pcb_data_t *data, *oldhack; + + 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); + + /* move subc into a local "buffer" */ + memset(&ctx, 0, sizeof(ctx)); + ctx.buffer.pcb = pcb_data_get_top((*subc)->data); + ctx.buffer.dst = pcb_data_new(NULL); + ctx.buffer.src = data; + + oldhack = pcb_pstk_data_hack; + pcb_pstk_data_hack = ctx.buffer.dst; + newsc = pcb_subcop_move_to_buffer(&ctx, *subc); + + + /* mirror object geometry and stackup */ + pcb_subc_mirror(NULL, newsc, yoff, pcb_true); + for(n = 0; n < newsc->data->LayerN; n++) { + pcb_layer_t *ly = newsc->data->Layer + n; + if (ly->meta.bound.type & PCB_LYT_TOP) + ly->meta.bound.type = (ly->meta.bound.type & ~PCB_LYT_TOP) | PCB_LYT_BOTTOM; + else if (ly->meta.bound.type & PCB_LYT_BOTTOM) + ly->meta.bound.type = (ly->meta.bound.type & ~PCB_LYT_BOTTOM) | PCB_LYT_TOP; + } + + /* place the new subc */ + newsc2 = pcb_subc_dup_at(pcb, data, newsc, 0, 0, pcb_true); + newsc2->ID = newsc->ID; + PCB_SET_PARENT(newsc2, data, data); + pcb_undo_add_subc_to_otherside(PCB_TYPE_SUBC, newsc2, newsc2, newsc2, yoff); + + *subc = newsc2; + pcb_subc_free(newsc); + pcb_data_free(ctx.buffer.dst); + pcb_pstk_data_hack = oldhack; + return pcb_true; +} + + +#include "conf_core.h" +#include "draw.h" +pcb_r_dir_t draw_subc_mark_callback(const pcb_box_t *b, void *cl) +{ + pcb_subc_t *subc = (pcb_subc_t *) b; + pcb_box_t *bb = &subc->BoundingBox; + int selected = PCB_FLAG_TEST(PCB_FLAG_SELECTED, subc); + + pcb_gui->set_color(pcb_draw_out.fgGC, conf_core.appearance.color.element); + pcb_gui->set_line_cap(pcb_draw_out.fgGC, Trace_Cap); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 1); + pcb_subc_draw_origin(subc, 0, 0); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 0); + + pcb_gui->set_color(pcb_draw_out.fgGC, selected ? conf_core.appearance.color.subc_selected : conf_core.appearance.color.subc); + pcb_gui->set_line_width(pcb_draw_out.fgGC, 0); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 1); + pcb_draw_dashed_line(pcb_draw_out.fgGC, bb->X1, bb->Y1, bb->X2, bb->Y1); + pcb_draw_dashed_line(pcb_draw_out.fgGC, bb->X1, bb->Y1, bb->X1, bb->Y2); + pcb_draw_dashed_line(pcb_draw_out.fgGC, bb->X2, bb->Y2, bb->X2, bb->Y1); + pcb_draw_dashed_line(pcb_draw_out.fgGC, bb->X2, bb->Y2, bb->X1, bb->Y2); + pcb_gui->set_draw_xor(pcb_draw_out.fgGC, 0); + + if (subc->refdes != NULL) { + pcb_coord_t x0, y0; + + if (conf_core.editor.view.flip_x) + x0 = bb->X2; + else + x0 = bb->X1; + if (conf_core.editor.view.flip_y) + y0 = bb->Y2; + else + y0 = bb->Y1; + + pcb_term_label_draw(x0, y0, 50.0, 0, 0, subc->refdes, subc->intconn); + } + + 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_pstk_draw_t ctx; + + 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_LYT_SILK | PCB_LYT_OUTLINE)) + pcb_draw_layer(layer, drawn_area); + } + + ctx.pcb = NULL; + ctx.gid = -1; + ctx.is_current = 1; + ctx.comb = 0; + pcb_r_search(sc->data->padstack_tree, drawn_area, NULL, pcb_pstk_draw_callback, &ctx, NULL); +} + + +pcb_subc_t *pcb_subc_by_refdes(pcb_data_t *base, const char *name) +{ +#warning subc TODO: 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. */ +#warning subc TODO: hierarchy + PCB_SUBC_LOOP(base); + { + if (subc->ID == ID) + return subc; + } + PCB_END_LOOP; + return NULL; +} Index: tags/1.2.7/src/obj_subc.h =================================================================== --- tags/1.2.7/src/obj_subc.h (nonexistent) +++ tags/1.2.7/src/obj_subc.h (revision 13657) @@ -0,0 +1,117 @@ +/* + * 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. + * + */ + +#ifndef PCB_OBJ_SUBC_H +#define PCB_OBJ_SUBC_H + +#include +#include +#include "obj_common.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_ANYOBJECTFIELDS; + 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); +void pcb_subc_free(pcb_subc_t *sc); + +void pcb_add_subc_to_data(pcb_data_t *dt, pcb_subc_t *sc); + +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); + +/* changes the side of the board an element 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 XORDrawSubc(pcb_subc_t *sc, pcb_coord_t DX, pcb_coord_t DY, int use_curr_side); + +/* Redo the binding after the layer binding recipe changed in sc */ +int pcb_subc_rebind(pcb_board_t *pcb, pcb_subc_t *sc); + +#include "rtree.h" +pcb_r_dir_t draw_subc_mark_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); + +/* 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 or brd_layer if not found. */ +pcb_layer_t *pcb_loose_subc_layer(pcb_board_t *pcb, pcb_layer_t *brd_layer); + +/*** loops ***/ + +#define PCB_SUBC_LOOP(top) do { \ + pcb_subc_t *subc; \ + gdl_iterator_t __it__; \ + subclist_foreach(&(top)->subc, &__it__, subc) { + + +#endif Index: tags/1.2.7/src/obj_subc_list.c =================================================================== --- tags/1.2.7/src/obj_subc_list.c (nonexistent) +++ tags/1.2.7/src/obj_subc_list.c (revision 13657) @@ -0,0 +1,32 @@ +/* + * 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. + * + */ + + + +#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/1.2.7/src/obj_subc_list.h =================================================================== --- tags/1.2.7/src/obj_subc_list.h (nonexistent) +++ tags/1.2.7/src/obj_subc_list.h (revision 13657) @@ -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. + * + */ + +#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 + +/* 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(const pcb_subc_t *e); + +/* Compare two subcs and return 1 if they contain the same objects. */ +int pcb_subc_eq(const pcb_subc_t *e1, const pcb_subc_t *e2); + +/* Create a new local variable to be used for deduplication */ +#define pcb_subclist_dedup_initializer(state) htep_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 = htep_alloc(pcb_subc_hash, pcb_subc_eq); \ + if (htep_has(state, loop_elem)) \ + continue; \ + htep_set(state, loop_elem, 1); \ + } \ +} + +/* use this after the loop to free all memory used by state */ +#define pcb_subclist_dedup_free(state) \ + do { \ + if (state != NULL) { \ + htep_free(state); \ + state = NULL; \ + } \ + } while(0) + + +#ifndef LIST_SUBCENT_NOINSTANT +#include +#include +#endif + +#endif Index: tags/1.2.7/src/obj_subc_op.h =================================================================== --- tags/1.2.7/src/obj_subc_op.h (nonexistent) +++ tags/1.2.7/src/obj_subc_op.h (revision 13657) @@ -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. + * + */ + +#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_to_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_clear_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_set_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_octagon(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_clear_square(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_set_square(pcb_opctx_t *ctx, pcb_subc_t *sc); +void *pcb_subcop_change_square(pcb_opctx_t *ctx, pcb_subc_t *sc); + +void *pcb_subcop_change_flag(pcb_opctx_t *ctx, pcb_subc_t *sc); + +void *pcb_subc_op(pcb_data_t *Data, pcb_subc_t *sc, pcb_opfunc_t *opfunc, pcb_opctx_t *ctx); + +#endif Index: tags/1.2.7/src/obj_subc_parent.h =================================================================== --- tags/1.2.7/src/obj_subc_parent.h (nonexistent) +++ tags/1.2.7/src/obj_subc_parent.h (revision 13657) @@ -0,0 +1,99 @@ +/* + * 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. + * + */ + +#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, 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, pcb_parent_t *p) +{ + if (pt != PCB_PARENT_LAYER) + return NULL; + + if (p->layer == NULL) + return NULL; + + if (p->layer->parent == NULL) + return NULL; + + if (p->layer->parent->parent_type == PCB_PARENT_SUBC) + return p->layer->parent->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(pcb_any_obj_t *obj) +{ + switch(obj->type) { + case PCB_OBJ_VIA: + 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); + +#if 0 + case PCB_OBJ_RATLINE: + /* easy case: can not be in a subc at all */ + return 0; + + case PCB_OBJ_PIN: + case PCB_OBJ_PAD: + case PCB_OBJ_ELEMENT_NAME: + case PCB_OBJ_ELEMENT: + case PCB_OBJ_ELEMENT_LINE: + case PCB_OBJ_ELEMENT_ARC: + /* easy case: these obsolete constructs can not be in a subc at all */ + return 0; +#endif + + default: + /* anything else: virtual */ + return 0; + } + return 0; +} + + +#endif Index: tags/1.2.7/src/obj_term.c =================================================================== --- tags/1.2.7/src/obj_term.c (nonexistent) +++ tags/1.2.7/src/obj_term.c (revision 13657) @@ -0,0 +1,353 @@ +/* + * 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. + * + */ + +#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 "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; + +#warning TODO: get rid of the two parallel type systems +extern unsigned long pcb_obj_type2oldtype(pcb_objtype_t type); + +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(pcb_obj_type2oldtype(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(pcb_obj_type2oldtype(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, 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, 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 && (!same || !PCB_FLAG_TEST(PCB_FLAG_DRC, ob))) { \ + 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 && (!same || !PCB_FLAG_TEST(PCB_FLAG_DRC, ob))) { \ + 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(pcb_board_t *pcb, pcb_data_t *data, pcb_layer_type_t lyt, const char *subc_name, const char *term_name, pcb_bool same, 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 pcb_false; + + 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: via and padstack */ + if (lyt & (PCB_LYT_COPPER | PCB_LYT_MASK | PCB_LYT_OUTLINE)) { + PCB_VIA_LOOP(subc->data) { + CHECK_TERM_GL(via); + } PCB_END_LOOP; + 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/1.2.7/src/obj_term.h =================================================================== --- tags/1.2.7/src/obj_term.h (nonexistent) +++ tags/1.2.7/src/obj_term.h (revision 13657) @@ -0,0 +1,86 @@ +/* + * 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. + * + */ + +/* 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" + +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(pcb_board_t *pcb, pcb_data_t *data, pcb_layer_type_t lyt, const char *subc_name, const char *term_name, pcb_bool same, pcb_subc_t **parent_out, pcb_layergrp_id_t *gid_out); + +#endif Index: tags/1.2.7/src/obj_text.c =================================================================== --- tags/1.2.7/src/obj_text.c (nonexistent) +++ tags/1.2.7/src/obj_text.c (revision 13657) @@ -0,0 +1,1028 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: text */ + +#include "config.h" + +#include "rotate.h" +#include "board.h" +#include "data.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "undo.h" +#include "polygon.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" + +/* 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 ***/ +/* get next slot for a text object, allocates memory if necessary */ +pcb_text_t *pcb_text_alloc(pcb_layer_t * layer) +{ + pcb_text_t *new_obj; + + new_obj = calloc(sizeof(pcb_text_t), 1); + new_obj->type = PCB_OBJ_TEXT; + new_obj->Attributes.post_change = pcb_obj_attrib_post_change; + PCB_SET_PARENT(new_obj, layer, layer); + + textlist_append(&layer->Text, new_obj); + + return new_obj; +} + +void pcb_text_free(pcb_text_t * data) +{ + textlist_remove(data); + free(data); +} + +/*** 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, unsigned Direction, int Scale, 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->Direction = Direction; + text->Flags = Flags; + text->Scale = Scale; + text->TextString = pcb_strdup(TextString); + text->fid = PCBFont->id; + text->ID = pcb_create_ID_get(); + + 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->Direction, src->Scale, 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->Direction, src->Scale, 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(NULL, 0, 0); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) text, 0); +} + +static int pcb_text_render_str_cb(void *ctx, gds_t *s, const char **input) +{ + 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] == '.')) { + 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; + 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) +{ + if (!PCB_FLAG_TEST(PCB_FLAG_DYNTEXT, text)) + return (unsigned char *)text->TextString; + + return (unsigned char *)pcb_strdup_subst(text->TextString, pcb_text_render_str_cb, text, PCB_SUBST_PERCENT | PCB_SUBST_CONF); +} + +/* 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; + + 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(PCB->minWid, PCB->minSlk) / 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->BoundingBox.X2); + maxy = MAX(maxy, arc->BoundingBox.X2); + } + + 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; + } + + /* scale values */ + minx = PCB_SCALE_TEXT(minx, Text->Scale); + miny = PCB_SCALE_TEXT(miny, Text->Scale); + maxx = PCB_SCALE_TEXT(maxx, Text->Scale); + maxy = PCB_SCALE_TEXT(maxy, Text->Scale); + + /* set upper-left and lower-right corner; + * swap coordinates if necessary (origin is already in 'swapped') + * and rotate box + */ + + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) { + Text->BoundingBox.X1 = Text->X + minx; + Text->BoundingBox.Y1 = Text->Y - miny; + Text->BoundingBox.X2 = Text->X + maxx; + Text->BoundingBox.Y2 = Text->Y - maxy; + pcb_box_rotate90(&Text->BoundingBox, Text->X, Text->Y, (4 - Text->Direction) & 0x03); + } + else { + Text->BoundingBox.X1 = Text->X + minx; + Text->BoundingBox.Y1 = Text->Y + miny; + Text->BoundingBox.X2 = Text->X + maxx; + Text->BoundingBox.Y2 = Text->Y + maxy; + pcb_box_rotate90(&Text->BoundingBox, Text->X, Text->Y, Text->Direction); + } + + /* the bounding box covers the extent of influence + * so it must include the clearance values too + */ + Text->BoundingBox.X1 -= PCB->Bloat; + Text->BoundingBox.Y1 -= PCB->Bloat; + Text->BoundingBox.X2 += PCB->Bloat; + Text->BoundingBox.Y2 += PCB->Bloat; + pcb_close_box(&Text->BoundingBox); + pcb_text_free_str(Text, rendered); +} + + + +/*** 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->Direction, Text->Scale, Text->TextString, pcb_flag_mask(Text->Flags, ctx->buffer.extraflg)); + + pcb_text_copy_meta(t, Text); + return t; +} + +/* moves a text to buffer without allocating memory for the name */ +void *pcb_textop_move_to_buffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text) +{ + pcb_layer_t *lay = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, layer)]; + + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *) text); + pcb_poly_restore_to_poly(ctx->buffer.src, PCB_TYPE_TEXT, layer, text); + + textlist_remove(text); + textlist_append(&lay->Text, text); + + if (!lay->text_tree) + lay->text_tree = pcb_r_create_tree(NULL, 0, 0); + pcb_r_insert_entry(lay->text_tree, (pcb_box_t *) text, 0); + pcb_poly_clear_from_poly(ctx->buffer.dst, PCB_TYPE_TEXT, lay, text); + + PCB_SET_PARENT(text, layer, lay); + + 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_TYPE_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_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_TEXT, Layer, Text, Text, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_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_TYPE_TEXT, Layer, Text, Text, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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->Direction, Text->Scale, 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_TYPE_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); + pcb_draw(); + } + 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_TYPE_TEXT, Layer, Text); + pcb_textop_move_noclip(ctx, Layer, Text); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_TEXT, Layer, Text); + } + if (ctx->clip.clear) { + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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_TYPE_TEXT, Source, text); + pcb_r_delete_entry(Source->text_tree, (pcb_box_t *) text); + + textlist_remove(text); + textlist_append(&Destination->Text, 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(NULL, 0, 0); + pcb_r_insert_entry(Destination->text_tree, (pcb_box_t *) text, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_TEXT, Destination, text); + + PCB_SET_PARENT(text, layer, Destination); + + 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, the object is locked\n")); + return NULL; + } + if (ctx->move.dst_layer != layer) { + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_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); + if (layer->meta.real.vis || ctx->move.dst_layer->meta.real.vis) + pcb_draw(); + } + 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); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_TEXT, Layer, Text, Text); + return NULL; +} + +void *pcb_text_destroy(pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + return pcb_textop_remove(&ctx, Layer, Text); +} + +/* 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) +{ + pcb_uint8_t number; + + number = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text) ? (4 - Number) & 3 : Number; + PCB_COORD_ROTATE90(Text->X, Text->Y, X, Y, Number); + + /* set new direction, 0..3, + * 0-> to the right, 1-> straight up, + * 2-> to the left, 3-> straight down + */ + Text->Direction = ((Text->Direction + number) & 0x03); + + /* 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_TYPE_TEXT, Layer, Text); + 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); + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_TEXT, Layer, Text); + pcb_text_invalidate_draw(Layer, Text); + pcb_draw(); + return (Text); +} + +void *pcb_textop_rotate(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + int steps; + pcb_text_invalidate_erase(Layer, Text); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_TEXT, Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + + steps = (int)ctx->rotate.angle / 90; + if (steps > 0) + Text->Direction = ((Text->Direction + steps) & 0x03); + + pcb_rotate(&Text->X, &Text->Y, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.cosa, ctx->rotate.sina); + pcb_text_bbox(NULL, Text); + + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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, 0); +} + +void pcb_text_set_font(pcb_layer_t *layer, pcb_text_t *text, pcb_font_id_t fid) +{ + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_TEXT, layer, text); +} + +void pcb_text_update(pcb_layer_t *layer, pcb_text_t *text) +{ + pcb_data_t *data = layer->parent; + pcb_board_t *pcb = pcb_data_get_top(data); + + if (pcb == NULL) + return; + + pcb_poly_restore_to_poly(data, PCB_TYPE_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, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_TEXT, layer, text); +} + +void *pcb_textop_change_flag(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + static pcb_flag_values_t pcb_text_flags = 0; + if (pcb_text_flags == 0) + pcb_text_flags = pcb_obj_valid_flags(PCB_TYPE_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); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_restore_to_poly(ctx->chgflag.pcb->Data, PCB_TYPE_TEXT, Text->parent.layer, Text); + + PCB_FLAG_CHANGE(ctx->chgflag.how, ctx->chgflag.flag, Text); + + if (ctx->chgflag.flag & PCB_FLAG_CLEARLINE) + pcb_poly_clear_from_poly(ctx->chgflag.pcb->Data, PCB_TYPE_TEXT, Text->parent.layer, Text); + + 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_text_t *Text, pcb_poly_t *poly, pcb_coord_t x0, int xordraw, 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_SCALE_TEXT(p->X + x0, Text->Scale); + y[n] = PCB_SCALE_TEXT(p->Y, Text->Scale); + PCB_COORD_ROTATE90(x[n], y[n], 0, 0, Text->Direction); + + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) { + x[n] = PCB_SWAP_SIGN_X(x[n]); + y[n] = PCB_SWAP_SIGN_Y(y[n]); + } + + x[n] += Text->X; + y[n] += Text->Y; + + if (xordraw && (n > 0)) + pcb_gui->draw_line(pcb_crosshair.GC, xordx + x[n-1], xordy + y[n-1], xordx + x[n], xordy + y[n]); + + } + + if (!xordraw) + pcb_gui->fill_polygon(pcb_draw_out.fgGC, poly->PointN, x, y); +} + + +/* --------------------------------------------------------------------------- + * lowlevel drawing routine for text objects + */ +static void DrawTextLowLevel_(pcb_text_t *Text, pcb_coord_t min_line_width, int xordraw, pcb_coord_t xordx, pcb_coord_t xordy) +{ + pcb_coord_t x = 0; + unsigned char *string, *rendered = pcb_text_render_str(Text); + pcb_cardinal_t n; + pcb_font_t *font = pcb_font(PCB, Text->fid, 1); + + string = rendered; + + 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; + + for (n = font->Symbol[*string].LineN; n; n--, line++) { + /* create one line, scale, move, rotate and swap it */ + newline = *line; + newline.Point1.X = PCB_SCALE_TEXT(newline.Point1.X + x, Text->Scale); + newline.Point1.Y = PCB_SCALE_TEXT(newline.Point1.Y, Text->Scale); + newline.Point2.X = PCB_SCALE_TEXT(newline.Point2.X + x, Text->Scale); + newline.Point2.Y = PCB_SCALE_TEXT(newline.Point2.Y, Text->Scale); + newline.Thickness = PCB_SCALE_TEXT(newline.Thickness, Text->Scale / 2); + if (newline.Thickness < min_line_width) + newline.Thickness = min_line_width; + + pcb_line_rotate90(&newline, 0, 0, Text->Direction); + + /* the labels of SMD objects on the bottom + * side haven't been swapped yet, only their offset + */ + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) { + newline.Point1.X = PCB_SWAP_SIGN_X(newline.Point1.X); + newline.Point1.Y = PCB_SWAP_SIGN_Y(newline.Point1.Y); + newline.Point2.X = PCB_SWAP_SIGN_X(newline.Point2.X); + newline.Point2.Y = PCB_SWAP_SIGN_Y(newline.Point2.Y); + } + /* add offset and draw line */ + newline.Point1.X += Text->X; + newline.Point1.Y += Text->Y; + newline.Point2.X += Text->X; + newline.Point2.Y += Text->Y; + 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_(&newline, 0); + } + + /* draw the arcs */ + for(a = arclist_first(&font->Symbol[*string].arcs); a != NULL; a = arclist_next(a)) { + newarc = *a; + + newarc.X = PCB_SCALE_TEXT(newarc.X + x, Text->Scale); + newarc.Y = PCB_SCALE_TEXT(newarc.Y, Text->Scale); + newarc.Height = newarc.Width = PCB_SCALE_TEXT(newarc.Height, Text->Scale); + newarc.Thickness = PCB_SCALE_TEXT(newarc.Thickness, Text->Scale / 2); + if (newarc.Thickness < min_line_width) + newarc.Thickness = min_line_width; + pcb_arc_rotate90(&newarc, 0, 0, Text->Direction); + + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, Text)) { + newarc.X = PCB_SWAP_SIGN_X(newarc.X); + newarc.Y = PCB_SWAP_SIGN_Y(newarc.Y); + newarc.StartAngle = PCB_SWAP_ANGLE(newarc.StartAngle); + newarc.Delta = PCB_SWAP_DELTA(newarc.Delta); + } + newarc.X += Text->X; + newarc.Y += Text->Y; + 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_(&newarc, 0); + } + + /* draw the polygons */ + for(p = polylist_first(&font->Symbol[*string].polys); p != NULL; p = polylist_next(p)) + draw_text_poly(Text, p, x, xordraw, 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_font_t *font = pcb_font(PCB, Text->fid, 1); + pcb_box_t defaultsymbol = font->DefaultSymbol; + pcb_coord_t size = (defaultsymbol.X2 - defaultsymbol.X1) * 6 / 5; + + defaultsymbol.X1 = PCB_SCALE_TEXT(defaultsymbol.X1 + x, Text->Scale); + defaultsymbol.Y1 = PCB_SCALE_TEXT(defaultsymbol.Y1, Text->Scale); + defaultsymbol.X2 = PCB_SCALE_TEXT(defaultsymbol.X2 + x, Text->Scale); + defaultsymbol.Y2 = PCB_SCALE_TEXT(defaultsymbol.Y2, Text->Scale); + + pcb_box_rotate90(&defaultsymbol, 0, 0, Text->Direction); + + /* add offset and draw box */ + defaultsymbol.X1 += Text->X; + defaultsymbol.Y1 += Text->Y; + defaultsymbol.X2 += Text->X; + defaultsymbol.Y2 += Text->Y; + pcb_gui->fill_rect(pcb_draw_out.fgGC, defaultsymbol.X1, defaultsymbol.Y1, defaultsymbol.X2, defaultsymbol.Y2); + + /* move on to next cursor position */ + x += size; + } + string++; + } + 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 *txt) +{ + if (txt->term != NULL) { + pcb_text_t text; + pcb_term_label_setup(&text, (txt->BoundingBox.X1 + txt->BoundingBox.X2)/2, (txt->BoundingBox.Y1 + txt->BoundingBox.Y2)/2, + 100.0, is_text_term_vert(txt), pcb_true, txt->term, txt->intconn); + pcb_draw_invalidate(&text); + } +} + +void pcb_text_draw_label(pcb_text_t *text) +{ + if (text->term != NULL) + pcb_term_label_draw((text->BoundingBox.X1 + text->BoundingBox.X2)/2, (text->BoundingBox.Y1 + text->BoundingBox.Y2)/2, + 100.0, is_text_term_vert(text), pcb_true, text->term, text->intconn); +} + + +void pcb_text_draw_(pcb_text_t *text, pcb_coord_t min_line_width, int allow_term_gfx) +{ + DrawTextLowLevel_(text, min_line_width, 0, 0, 0); + + if (text->term != NULL) { + if ((allow_term_gfx) && ((pcb_draw_doing_pinout) || PCB_FLAG_TEST(PCB_FLAG_TERMNAME, text))) + pcb_draw_delay_label_add((pcb_any_obj_t *)text); + } +} + +static void pcb_text_draw(pcb_layer_t *layer, pcb_text_t *text, int allow_term_gfx) +{ + int min_silk_line; + unsigned int flg = 0; + + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + pcb_gui->set_color(pcb_draw_out.fgGC, layer->meta.real.selected_color); + else if (PCB_HAS_COLOROVERRIDE(text)) { + pcb_gui->set_color(pcb_draw_out.fgGC, text->override_color); + } + else if (layer->is_bound) { + const char *color; + PCB_OBJ_COLOR_ON_BOUND_LAYER(color, layer); + 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 = PCB->minSlk; + else + min_silk_line = PCB->minWid; + + pcb_text_draw_(text, min_silk_line, allow_term_gfx); +} + +pcb_r_dir_t pcb_text_draw_callback(const pcb_box_t * b, void *cl) +{ + pcb_layer_t *layer = cl; + pcb_text_t *text = (pcb_text_t *) b; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(text->parent_type, &text->parent)) + return PCB_R_DIR_FOUND_CONTINUE; + + pcb_text_draw(layer, 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_layer_t *layer = cl; + pcb_text_t *text = (pcb_text_t *) b; + + if (!PCB->SubcPartsOn && pcb_lobj_parent_subc(text->parent_type, &text->parent)) + return PCB_R_DIR_FOUND_CONTINUE; + + pcb_text_draw(layer, 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_(text, 0, 1, x, y); +} + +/*** 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_ELEMENT_LOOP(data); { + PCB_ELEMENT_PCB_TEXT_LOOP(element); { + if (text->fid == fid) { + pcb_element_text_update(PCB, data, element, n); + 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, 0); + } + } 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); +} + +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/1.2.7/src/obj_text.h =================================================================== --- tags/1.2.7/src/obj_text.h (nonexistent) +++ tags/1.2.7/src/obj_text.h (revision 13657) @@ -0,0 +1,106 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Drawing primitive: text */ + +#ifndef PCB_OBJ_TEXT_H +#define PCB_OBJ_TEXT_H + +#include "obj_common.h" +#include "font.h" + +struct pcb_text_s { + PCB_ANYOBJECTFIELDS; + int Scale; /* text scaling in percent */ + pcb_coord_t X, Y; /* origin */ + pcb_uint8_t Direction; + pcb_font_id_t fid; + char *TextString; /* string */ + void *Element; /* TODO: remove this in favor of generic parenting */ + gdl_elem_t link; /* a text is in a list of a layer or an element */ +}; + +/* 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); +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, unsigned Direction, int Scale, 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_flip_side(pcb_layer_t *layer, pcb_text_t *text, pcb_coord_t y_offs); +void pcb_text_set_font(pcb_layer_t *layer, pcb_text_t *text, pcb_font_id_t fid); +void pcb_text_update(pcb_layer_t *layer, pcb_text_t *text); + +/* 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); + +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_MOVE((__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__; \ + linelist_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_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/1.2.7/src/obj_text_draw.h =================================================================== --- tags/1.2.7/src/obj_text_draw.h (nonexistent) +++ tags/1.2.7/src/obj_text_draw.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** Standard draw of text ***/ + + +/* 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 + +void pcb_text_draw_(pcb_text_t *Text, pcb_coord_t min_line_width, int allow_term_gfx); +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_text_t *text); + + Index: tags/1.2.7/src/obj_text_list.c =================================================================== --- tags/1.2.7/src/obj_text_list.c (nonexistent) +++ tags/1.2.7/src/obj_text_list.c (revision 13657) @@ -0,0 +1,29 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +/* 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/1.2.7/src/obj_text_list.h =================================================================== --- tags/1.2.7/src/obj_text_list.h (nonexistent) +++ tags/1.2.7/src/obj_text_list.h (revision 13657) @@ -0,0 +1,43 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/obj_text_op.h =================================================================== --- tags/1.2.7/src/obj_text_op.h (nonexistent) +++ tags/1.2.7/src/obj_text_op.h (revision 13657) @@ -0,0 +1,50 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/*** 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_to_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_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/1.2.7/src/object_act.c =================================================================== --- tags/1.2.7/src/object_act.c (nonexistent) +++ tags/1.2.7/src/object_act.c (revision 13657) @@ -0,0 +1,1386 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.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 "copy.h" +#include "remove.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "layer_vis.h" +#include "operation.h" + +/* --------------------------------------------------------------------------- */ + +static pcb_element_t *element_cache = NULL; + +static pcb_element_t *find_element_by_refdes(const char *refdes) +{ + if (element_cache && PCB_ELEM_NAME_REFDES(element_cache) + && strcmp(PCB_ELEM_NAME_REFDES(element_cache), refdes) == 0) + return element_cache; + + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_ELEM_NAME_REFDES(element) + && strcmp(PCB_ELEM_NAME_REFDES(element), refdes) == 0) { + element_cache = element; + return element_cache; + } + } + PCB_END_LOOP; + return NULL; +} + +#warning subc TODO: remove this when removing element support +static pcb_attribute_t *lookup_attr(pcb_attribute_list_t *list, const char *name) +{ + int i; + for (i = 0; i < list->Number; i++) + if (strcmp(list->List[i].name, name) == 0) + return &list->List[i]; + return NULL; +} + +#warning subc TODO: remove this when removing element support +static void delete_attr(pcb_attribute_list_t *list, pcb_attribute_t * attr) +{ + int idx = attr - list->List; + if (idx < 0 || idx >= list->Number) + return; + if (list->Number - idx > 1) + memmove(attr, attr + 1, (list->Number - idx - 1) * sizeof(pcb_attribute_t)); + list->Number--; +} + +/* ------------------------------------------------------------ */ + +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 element or subcircuit."; + +/* %start-doc actions Attributes + +This just pops up a dialog letting the user edit the attributes of the +pcb, an element, or a layer. + +%end-doc */ + + +static int pcb_act_Attributes(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *layername = PCB_ACTION_ARG(1); + char *buf; + + if (!function) + PCB_ACT_FAIL(Attributes); + + if (!pcb_gui->edit_attributes) { + pcb_message(PCB_MSG_ERROR, _("This GUI doesn't support Attribute Editing\n")); + return 1; + } + + switch (pcb_funchash_get(function, NULL)) { + 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: + { + int n_found = 0; + pcb_element_t *e = NULL; + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + e = element; + n_found++; + } + } + PCB_END_LOOP; + if (n_found > 1) { + pcb_message(PCB_MSG_ERROR, _("Too many elements selected\n")); + return 1; + } + if (n_found == 0) { + void *ptrtmp; + pcb_gui->get_coords(_("Click on an element"), &x, &y); + if ((pcb_search_screen(x, y, PCB_TYPE_ELEMENT, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) + e = (pcb_element_t *) ptrtmp; + else { + pcb_message(PCB_MSG_ERROR, _("No element found there\n")); + return 1; + } + } + + if (PCB_ELEM_NAME_REFDES(e)) { + buf = (char *) malloc(strlen(PCB_ELEM_NAME_REFDES(e)) + strlen("Element X Attributes")); + sprintf(buf, "Element %s Attributes", PCB_ELEM_NAME_REFDES(e)); + } + else { + buf = pcb_strdup("Unnamed Element Attributes"); + } + pcb_gui->edit_attributes(buf, &(e->Attributes)); + free(buf); + break; + } + + 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) { + void *ptrtmp; + pcb_gui->get_coords(_("Click on a subcircuit"), &x, &y); + if ((pcb_search_screen(x, y, PCB_TYPE_SUBC, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) + s = (pcb_subc_t *)ptrtmp; + else { + pcb_message(PCB_MSG_ERROR, _("No subcricuit found there\n")); + return 1; + } + } + + 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 elements."; + +/* %start-doc actions DisperseElements + +Normally this is used when starting a board, by selecting all elements +and then dispersing them. This scatters the elements around the board +so that you can pick individual ones, rather than have all the +elements at the same 0,0 coordinate and thus impossible to choose +from. + +%end-doc */ + +#define GAP PCB_MIL_TO_COORD(100) + +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) +{ + /* 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; + + /* keep track of how tall this row is */ + *minx += obj->BoundingBox.X2 - obj->BoundingBox.X1 + GAP; + if (*maxy < obj->BoundingBox.Y2) + *maxy = obj->BoundingBox.Y2; +} + +static int pcb_act_DisperseElements(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + pcb_coord_t minx = GAP, miny = GAP, maxy = GAP, dx, dy; + int all = 0, bad = 0; + + if (!function || !*function) { + bad = 1; + } + else { + switch (pcb_funchash_get(function, NULL)) { + case F_All: + all = 1; + break; + + case F_Selected: + all = 0; + break; + + default: + bad = 1; + } + } + + if (bad) { + PCB_ACT_FAIL(DisperseElements); + } + + pcb_draw_inhibit_inc(); + PCB_ELEMENT_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) && (all || PCB_FLAG_TEST(PCB_FLAG_SELECTED, element))) { + disperse_obj(PCB, (pcb_any_obj_t *)element, element->MarkX, element->MarkY, &dx, &dy, &minx, &miny, &maxy); + + /* move the element */ + pcb_element_move(PCB->Data, element, dx, dy); + + /* and add to the undo list so we can undo this operation */ + pcb_undo_add_obj_to_move(PCB_TYPE_ELEMENT, NULL, NULL, element, dx, dy); + } + } + PCB_END_LOOP; + + 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, &x, &y) != 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_TYPE_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|SelectedElements)"; + +static const char pcb_acth_Flip[] = "Flip an element to the opposite side of the board."; + +/* %start-doc actions Flip + +Note that the location of the element 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 element is on the other side. When flipping +multiple elements, this retains their positions relative to each +other, not their absolute positions on the board. + +%end-doc */ + +static int pcb_act_Flip(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + pcb_element_t *element; + void *ptrtmp; + int err = 0; + + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + if ((pcb_search_screen(x, y, PCB_TYPE_ELEMENT, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) { + element = (pcb_element_t *) ptrtmp; + pcb_undo_save_serial(); + pcb_element_change_side(element, 2 * pcb_crosshair.Y - PCB->MaxHeight); + pcb_undo_inc_serial(); + pcb_draw(); + } + if ((pcb_search_screen(x, y, PCB_TYPE_SUBC, &ptrtmp, &ptrtmp, &ptrtmp)) != PCB_TYPE_NONE) { + pcb_subc_t *subc = (pcb_subc_t *)ptrtmp; + pcb_undo_save_serial(); + pcb_subc_change_side(&subc, 2 * pcb_crosshair.Y - PCB->MaxHeight); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + case F_Selected: + case F_SelectedElements: + pcb_undo_save_serial(); + pcb_selected_subc_change_side(); + pcb_selected_element_change_side(); + pcb_undo_inc_serial(); + pcb_draw(); + break; + default: + err = 1; + break; + } + if (!err) + return 0; + } + + PCB_ACT_FAIL(Flip); +} +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_MoveObject[] = "pcb_move_obj(X,Y,dim)"; + +static const char pcb_acth_MoveObject[] = "Moves the object under the crosshair."; + +/* %start-doc actions MoveObject + +The @code{X} and @code{Y} are treated like @code{delta} is for many +other objects. For each, if it's prefixed by @code{+} or @code{-}, +then that amount is relative. Otherwise, it's absolute. Units can be +@code{mil} or @code{mm}; if unspecified, units are PCB's internal +units, currently 1/100 mil. + +%end-doc */ + +static int pcb_act_MoveObject(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *x_str = PCB_ACTION_ARG(0); + const char *y_str = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_coord_t nx, ny; + pcb_bool absolute1, absolute2; + void *ptr1, *ptr2, *ptr3; + int type; + + ny = pcb_get_value(y_str, units, &absolute1, NULL); + nx = pcb_get_value(x_str, units, &absolute2, NULL); + + type = pcb_search_screen(x, y, PCB_MOVE_TYPES, &ptr1, &ptr2, &ptr3); + if (type == PCB_TYPE_NONE) { + pcb_message(PCB_MSG_ERROR, _("Nothing found under crosshair\n")); + return 1; + } + if (absolute1) + nx -= x; + if (absolute2) + ny -= 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_TYPE_ELEMENT) + pcb_event(PCB_EVENT_RUBBER_LOOKUP_RATS, "ippp", type, ptr1, ptr2, ptr3); + pcb_move_obj_and_rubberband(type, ptr1, ptr2, ptr3, nx, ny); + pcb_board_set_changed_flag(pcb_true); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_MoveToCurrentLayer[] = "MoveToCurrentLayer(Object|SelectedObjects)"; + +static const char pcb_acth_MoveToCurrentLayer[] = "Moves objects to the current layer."; + +/* %start-doc actions MoveToCurrentLayer + +Note that moving an element from a component layer to a solder layer, +or from solder to component, won't automatically flip it. Use the +@code{Flip()} action to do that. + +%end-doc */ + +static int pcb_act_MoveToCurrentLayer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_MOVETOLAYER_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + if (pcb_move_obj_to_layer(type, ptr1, ptr2, ptr3, CURRENT, 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."; + +/* %start-doc actions elementlist + +@table @code + +@item Start +Indicates the start of an element list; call this before any Need +actions. + +@item Need +Searches the board for an element with a matching refdes. + +If found, the value and footprint are updated. + +If not found, a new element is created with the given footprint and value. + +@item Done +Compares the list of elements needed since the most recent +@code{start} with the list of elements actually on the board. Any +elements that weren't listed are selected, so that the user may delete +them. + +@end table + +%end-doc */ + +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, "name"); + 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 int pcb_act_ElementList(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_element_t *e = NULL; + pcb_subc_t *sc; + const char *refdes, *value, *footprint; + const char *args[3]; + const char *function = argv[0]; + char *old; + +#ifdef DEBUG + printf("Entered pcb_act_ElementList, executing function %s\n", function); +#endif + + if (pcb_strcasecmp(function, "start") == 0) { + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, element); + } + PCB_END_LOOP; + element_cache = NULL; + number_of_footprints_not_found = 0; + return 0; + } + + if (pcb_strcasecmp(function, "done") == 0) { + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, element)) { + PCB_FLAG_CLEAR(PCB_FLAG_FOUND, element); + } + else if (!PCB_EMPTY_STRING_P(PCB_ELEM_NAME_REFDES(element))) { + /* Unnamed elements should remain untouched */ + PCB_FLAG_SET(PCB_FLAG_SELECTED, element); + } + } + PCB_END_LOOP; + if (number_of_footprints_not_found > 0) + pcb_gui->confirm_dialog("Not all requested footprints were found.\n" "See the message log for details", "Ok", NULL); + return 0; + } + + if (pcb_strcasecmp(function, "need") != 0) + PCB_ACT_FAIL(ElementList); + + if (argc != 4) + PCB_ACT_FAIL(ElementList); + + argc--; + argv++; + + refdes = PCB_ACTION_ARG(0); + footprint = PCB_ACTION_ARG(1); + value = PCB_ACTION_ARG(2); + + args[0] = footprint; + args[1] = refdes; + args[2] = value; + +#ifdef DEBUG + printf(" ... footprint = %s\n", footprint); + printf(" ... refdes = %s\n", refdes); + printf(" ... value = %s\n", value); +#endif + + e = find_element_by_refdes(refdes); + sc = pcb_subc_by_refdes(PCB->Data, refdes); + + if ((e == NULL) && (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_LoadFootprint(argc, args, x, y)) { + number_of_footprints_not_found++; + return 1; + } + + 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. */ + if (pcb_buffer_copy_to_layout(PCB, nx, ny)) + pcb_board_set_changed_flag(pcb_true); + } + else if ( + (e && PCB_ELEM_NAME_DESCRIPTION(e) && strcmp(PCB_ELEM_NAME_DESCRIPTION(e), footprint) != 0) + || (sc && subc_differs(sc, footprint)) + ) + { +#ifdef DEBUG + printf(" ... Footprint on board, but different from footprint loaded.\n"); +#endif + int orig_on_top, orig_rotstep, paste_ok = 0; + pcb_coord_t orig_cx, orig_cy; + pcb_element_t *pe; + double orig_rot; + + /* Different footprint, we need to swap them out. */ + if (pcb_act_LoadFootprint(argc, args, x, y) != 0) { + number_of_footprints_not_found++; + return 1; + } + + /* save the rotation value of the original element/subc */ + if (e != NULL) { + orig_rotstep = pcb_element_get_orientation(e); + orig_rot = orig_rotstep * 90.0; + orig_cx = e->MarkX; + orig_cy = e->MarkY; + orig_on_top = PCB_FRONT(e); + } + else { + orig_rot = 0.0; + orig_cx = 0; + orig_cy = 0; + orig_on_top = 0; + pcb_subc_get_rotation(sc, &orig_rot); + orig_rotstep = pcb_round(orig_rot / 90.0); + pcb_subc_get_origin(sc, &orig_cx, &orig_cy); + pcb_subc_get_side(sc, &orig_on_top); + orig_on_top = !orig_on_top; + } + + pe = elementlist_first(&(PCB_PASTEBUFFER->Data->Element)); + if (pe != NULL) { + /* replace with element */ + int pr, i; + + if (!orig_on_top) + pcb_element_mirror(PCB_PASTEBUFFER->Data, pe, pe->MarkY * 2 - PCB->MaxHeight); + + pr = pcb_element_get_orientation(pe); + + if (orig_rotstep != pr) + pcb_element_rotate90(PCB_PASTEBUFFER->Data, pe, pe->MarkX, pe->MarkY, (orig_rotstep - pr + 4) % 4); + + for (i = 0; i < PCB_MAX_ELEMENTNAMES; i++) { + pe->Name[i].X = e->Name[i].X - orig_cx + pe->MarkX; + pe->Name[i].Y = e->Name[i].Y - orig_cy + pe->MarkY; + pe->Name[i].Direction = e->Name[i].Direction; + pe->Name[i].Scale = e->Name[i].Scale; + } + + paste_ok = 1; + } + else { + /* 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 (e != NULL) + pcb_element_remove(e); + 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 */ + element_cache = NULL; + e = find_element_by_refdes(refdes); + if (e != NULL) { + old = pcb_element_text_change(PCB, PCB->Data, e, PCB_ELEMNAME_IDX_REFDES, pcb_strdup(refdes)); + if (old) + free(old); + old = pcb_element_text_change(PCB, PCB->Data, e, PCB_ELEMNAME_IDX_VALUE, pcb_strdup(value)); + if (old) + free(old); + PCB_FLAG_SET(PCB_FLAG_FOUND, e); + } + + 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 + + return 0; +} + +/* ---------------------------------------------------------------- */ +#warning subc TODO: remove this when removing element support +static const char pcb_acts_ElementSetAttr[] = "ElementSetAttr(refdes,name[,value])"; + +static const char pcb_acth_ElementSetAttr[] = "Sets or clears an element-specific attribute."; + +/* %start-doc actions elementsetattr + +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. + +%end-doc */ + +static int pcb_act_ElementSetAttr(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_element_t *e = NULL; + pcb_subc_t *sc; + const char *refdes, *name, *value; + pcb_attribute_t *attr; + + if (argc < 2) { + PCB_ACT_FAIL(ElementSetAttr); + } + + refdes = argv[0]; + name = argv[1]; + value = PCB_ACTION_ARG(2); + + + sc = pcb_subc_by_refdes(PCB->Data, refdes); + if (sc != NULL) { + attr = lookup_attr(&sc->Attributes, name); + + if (attr && value) { + free(attr->value); + attr->value = pcb_strdup(value); + } + if (attr && !value) + delete_attr(&sc->Attributes, attr); + if (!attr && value) + pcb_attribute_put(&sc->Attributes, name, value); + return 0; + } + + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_NSTRCMP(refdes, PCB_ELEM_NAME_REFDES(element)) == 0) { + e = element; + break; + } + } + PCB_END_LOOP; + + if (!e) { + pcb_message(PCB_MSG_ERROR, _("Cannot change attribute of %s - element not found\n"), refdes); + return 1; + } + + attr = lookup_attr(&e->Attributes, name); + + if (attr && value) { + free(attr->value); + attr->value = pcb_strdup(value); + } + if (attr && !value) { + delete_attr(&e->Attributes, attr); + } + if (!attr && value) { + pcb_attribute_put(&e->Attributes, name, value); + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_RipUp[] = "RipUp(All|Selected|Element)"; + +static const char pcb_acth_RipUp[] = "Ripup auto-routed tracks, or convert an element to parts."; + +/* %start-doc actions RipUp + +@table @code + +@item All +Removes all lines and vias which were created by the autorouter. + +@item Selected +Removes all selected lines and vias which were created by the +autorouter. + +@item Element +Converts the element under the cursor to parts (vias and lines). Note +that this uses the highest numbered paste buffer. + +@end table + +%end-doc */ + +static int pcb_act_RipUp(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + pcb_bool changed = pcb_false; + + if (function) { + switch (pcb_funchash_get(function, NULL)) { + 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_TYPE_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_TYPE_ARC, layer, arc, arc); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_AUTO, via) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, via)) { + pcb_remove_object(PCB_TYPE_VIA, via, via, via); + 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_TYPE_LINE, layer, line, line); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (PCB->ViaOn) + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAGS_TEST(PCB_FLAG_AUTO | PCB_FLAG_SELECTED, via) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, via)) { + pcb_remove_object(PCB_TYPE_VIA, via, via, via); + changed = pcb_true; + } + } + PCB_END_LOOP; + if (changed) { + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } + break; + case F_Element: + { + void *ptr1, *ptr2, *ptr3; + pcb_coord_t gx, gy; + pcb_gui->get_coords("Click on an element", &gx, &gy); + if (pcb_search_screen(gx, gy, PCB_TYPE_ELEMENT, &ptr1, &ptr2, &ptr3) != PCB_TYPE_NONE) { + pcb_tool_note.Buffer = conf_core.editor.buffer_number; + pcb_buffer_set_number(PCB_MAX_BUFFER - 1); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_copy_obj_to_buffer(PCB, PCB_PASTEBUFFER->Data, PCB->Data, PCB_TYPE_ELEMENT, ptr1, ptr2, ptr3); + pcb_element_smash_buffer(PCB_PASTEBUFFER); + PCB_PASTEBUFFER->X = 0; + PCB_PASTEBUFFER->Y = 0; + pcb_undo_save_serial(); + pcb_erase_obj(PCB_TYPE_ELEMENT, ptr1, ptr1); + pcb_undo_move_obj_to_remove(PCB_TYPE_ELEMENT, ptr1, ptr2, ptr3); + pcb_undo_restore_serial(); + pcb_buffer_copy_to_layout(PCB, 0, 0); + pcb_buffer_set_number(pcb_tool_note.Buffer); + pcb_board_set_changed_flag(pcb_true); + } + } + break; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_MinMaskGap[] = "MinMaskGap(delta)\n" "MinMaskGap(Selected, delta)"; + +static const char pcb_acth_MinMaskGap[] = "Ensures the mask is a minimum distance from pins and pads."; + +/* %start-doc actions MinMaskGap + +Checks all specified pins and/or pads, and increases the mask if +needed to ensure a minimum distance between the pin or pad edge and +the mask edge. + +%end-doc */ + +static int pcb_act_MinMaskGap(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *delta = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_bool absolute; + pcb_coord_t value; + int flags; + + if (!function) + return 1; + 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(); + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (!PCB_FLAGS_TEST(flags, pin)) + continue; + if (pin->Mask < pin->Thickness + value) { + pcb_chg_obj_mask_size(PCB_TYPE_PIN, element, pin, 0, pin->Thickness + value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (!PCB_FLAGS_TEST(flags, pad)) + continue; + if (pad->Mask < pad->Thickness + value) { + pcb_chg_obj_mask_size(PCB_TYPE_PAD, element, pad, 0, pad->Thickness + value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; +#warning padstack TODO + PCB_VIA_LOOP(PCB->Data); + { + if (!PCB_FLAGS_TEST(flags, via)) + continue; + if (via->Mask && via->Mask < via->Thickness + value) { + pcb_chg_obj_mask_size(PCB_TYPE_VIA, via, 0, 0, via->Thickness + value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + 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."; + +/* %start-doc actions MinClearGap + +Checks all specified objects, and increases the polygon clearance if +needed to ensure a minimum distance between their edges and the +polygon edges. + +%end-doc */ + +static int pcb_act_MinClearGap(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + const char *delta = PCB_ACTION_ARG(1); + const char *units = PCB_ACTION_ARG(2); + pcb_bool absolute; + pcb_coord_t value; + int flags; + + if (!function) + return 1; + 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(); + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (!PCB_FLAGS_TEST(flags, pin)) + continue; + if (pin->Clearance < value) { + pcb_chg_obj_clear_size(PCB_TYPE_PIN, element, pin, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (!PCB_FLAGS_TEST(flags, pad)) + continue; + if (pad->Clearance < value) { + pcb_chg_obj_clear_size(PCB_TYPE_PAD, element, pad, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; +#warning padstack TODO + PCB_VIA_LOOP(PCB->Data); + { + if (!PCB_FLAGS_TEST(flags, via)) + continue; + if (via->Clearance < value) { + pcb_chg_obj_clear_size(PCB_TYPE_VIA, via, 0, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(PCB->Data); + { + if (!PCB_FLAGS_TEST(flags, line)) + continue; + if ((line->Clearance != 0) && (line->Clearance < value)) { + pcb_chg_obj_clear_size(PCB_TYPE_LINE, layer, line, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(PCB->Data); + { + if (!PCB_FLAGS_TEST(flags, arc)) + continue; + if ((arc->Clearance != 0) && (arc->Clearance < value)) { + pcb_chg_obj_clear_size(PCB_TYPE_ARC, layer, arc, 0, value, 1); + pcb_undo_restore_serial(); + } + } + PCB_ENDALL_LOOP; + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + return 0; +} + +/* --------------------------------------------------------------------------- */ +int pcb_act_ListRotations(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + PCB_ELEMENT_LOOP(PCB->Data); + { + printf("%d %s\n", pcb_element_get_orientation(element), PCB_ELEM_NAME_REFDES(element)); + } + PCB_END_LOOP; +#warning subc TODO +#warning cleanup TODO: move this to oldactions maybe? + return 0; +} + + +/* --------------------------------------------------------------------------- */ + +static const char movelayer_syntax[] = "MoveLayer(old,new)"; + +static const char movelayer_help[] = "Moves/Creates/Deletes Layers."; + +/* %start-doc actions MoveLayer + +Moves a layer, creates a new layer, or deletes a layer. + +@table @code + +@item old +The is the layer number to act upon. Allowed values are: +@table @code + +@item c +Currently selected layer. + +@item -1 +Create a new layer. + +@item number +An existing layer number. + +@end table + +@item new +Specifies where to move the layer to. Allowed values are: +@table @code +@item -1 +Deletes the layer. + +@item up +Moves the layer up. + +@item down +Moves the layer down. + +@item step+ +Moves the layer towards the end of its group's list. + +@item step- +Moves the layer towards the beginning of its group's list. + +@item c +Creates a new layer. + +@end table + +@end table + +%end-doc */ +extern pcb_layergrp_id_t pcb_actd_EditGroup_gid; +int pcb_act_MoveLayer(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int old_index, new_index; + + if (argc != 2) { + pcb_message(PCB_MSG_ERROR, "Usage; MoveLayer(old,new)"); + return 1; + } + + if (strcmp(argv[0], "c") == 0) + old_index = INDEXOFCURRENT; + else + old_index = atoi(argv[0]); + + if (strcmp(argv[1], "c") == 0) { + new_index = INDEXOFCURRENT; + if (new_index < 0) + new_index = 0; + } + else if (strcmp(argv[1], "gi") == 0) { + return pcb_layer_move(PCB, -1, 0, pcb_actd_EditGroup_gid); + } + else if (strcmp(argv[1], "ga") == 0) { + return pcb_layer_move(PCB, -1, 1, pcb_actd_EditGroup_gid); + } + else if (strcmp(argv[1], "up") == 0) { + new_index = INDEXOFCURRENT - 1; + if (new_index < 0) + return 1; + } + else if (strcmp(argv[1], "down") == 0) { + new_index = INDEXOFCURRENT + 1; + if (new_index >= pcb_max_layer) + return 1; + } + else if (strncmp(argv[1], "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(argv[1][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"); + return 1; + } + + else + new_index = atoi(argv[1]); + + 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"); + return 1; + } + } + } + + if (pcb_layer_move(PCB, old_index, new_index, -1)) + return 1; + + return 0; +} + +static pcb_layer_t *pick_layer(const char *user_text) +{ + char *end; + pcb_layer_id_t id; + if (*user_text == '#') { + id = strtol(user_text+1, &end, 10); + if (*end == '\0') + return pcb_get_layer(PCB->Data, id); + } + return NULL; +} + +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 int pcb_act_CreateText(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_layer_t *ly; + int fid = 0, dir = 0, scale = 0; + pcb_bool succ; + + if (argc != 7) + PCB_ACT_FAIL(CreateText); + + ly = pick_layer(argv[0]); + if (ly == NULL) { + pcb_message(PCB_MSG_ERROR, "Unknown layer %s", argv[0]); + return 1; + } + + fid = atoi(argv[1]); + x = pcb_get_value_ex(argv[2], NULL, NULL, NULL, "mm", &succ); + if (!succ) { + pcb_message(PCB_MSG_ERROR, "Invalid X coord %s", argv[2]); + return 1; + } + y = pcb_get_value_ex(argv[3], NULL, NULL, NULL, "mm", &succ); + if (!succ) { + pcb_message(PCB_MSG_ERROR, "Invalid Y coord %s", argv[3]); + return 1; + } + dir = atoi(argv[4]); + scale = atoi(argv[5]); + if (scale < 1) { + pcb_message(PCB_MSG_ERROR, "Invalid scale coord %s", argv[5]); + return 1; + } + + pcb_text_new(ly, pcb_font(PCB, fid, 1), x, y, dir, scale, argv[6], pcb_no_flags()); + + return 0; +} + + +pcb_hid_action_t object_action_list[] = { + {"Attributes", 0, pcb_act_Attributes, + pcb_acth_Attributes, pcb_acts_Attributes} + , + {"DisperseElements", 0, pcb_act_DisperseElements, + pcb_acth_DisperseElements, pcb_acts_DisperseElements} + , + {"Flip", N_("Click on Object or Flip Point"), pcb_act_Flip, + pcb_acth_Flip, pcb_acts_Flip} + , + {"ListRotations", 0, pcb_act_ListRotations, + 0, 0} + , + {"MoveObject", N_("Select an Object"), pcb_act_MoveObject, + pcb_acth_MoveObject, pcb_acts_MoveObject} + , + {"MoveToCurrentLayer", 0, pcb_act_MoveToCurrentLayer, + pcb_acth_MoveToCurrentLayer, pcb_acts_MoveToCurrentLayer} + , + {"ElementList", 0, pcb_act_ElementList, + pcb_acth_ElementList, pcb_acts_ElementList} + , + {"ElementSetAttr", 0, pcb_act_ElementSetAttr, + pcb_acth_ElementSetAttr, pcb_acts_ElementSetAttr} + , + {"RipUp", 0, pcb_act_RipUp, + pcb_acth_RipUp, pcb_acts_RipUp} + , + {"MinMaskGap", 0, pcb_act_MinMaskGap, + pcb_acth_MinMaskGap, pcb_acts_MinMaskGap} + , + {"MinClearGap", 0, pcb_act_MinClearGap, + pcb_acth_MinClearGap, pcb_acts_MinClearGap} + , + {"MoveLayer", 0, pcb_act_MoveLayer, + movelayer_help, movelayer_syntax} + , + {"CreateText", 0, pcb_act_CreateText, + pcb_acth_CreateText, pcb_acts_CreateText} +}; + +PCB_REGISTER_ACTIONS(object_action_list, NULL) Index: tags/1.2.7/src/operation.c =================================================================== --- tags/1.2.7/src/operation.c (nonexistent) +++ tags/1.2.7/src/operation.c (revision 13657) @@ -0,0 +1,335 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "config.h" + +#include "operation.h" +#include "const.h" +#include "board.h" +#include "data.h" +#include "conf_core.h" +#include "undo.h" +#include "rats.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_TYPE_LINE: + if (F->Line) + return (F->Line(ctx, (pcb_layer_t *) Ptr1, (pcb_line_t *) Ptr2)); + break; + + case PCB_TYPE_ARC: + if (F->Arc) + return (F->Arc(ctx, (pcb_layer_t *) Ptr1, (pcb_arc_t *) Ptr2)); + break; + + case PCB_TYPE_LINE_POINT: + if (F->LinePoint) + return (F->LinePoint(ctx, (pcb_layer_t *) Ptr1, (pcb_line_t *) Ptr2, (pcb_point_t *) Ptr3)); + break; + + case PCB_TYPE_ARC_POINT: + if (F->ArcPoint) + return (F->ArcPoint(ctx, (pcb_layer_t *) Ptr1, (pcb_arc_t *) Ptr2, (int *) Ptr3)); + break; + + case PCB_TYPE_TEXT: + if (F->Text) + return (F->Text(ctx, (pcb_layer_t *) Ptr1, (pcb_text_t *) Ptr2)); + break; + + case PCB_TYPE_POLY: + if (F->Polygon) + return (F->Polygon(ctx, (pcb_layer_t *) Ptr1, (pcb_poly_t *) Ptr2)); + break; + + case PCB_TYPE_POLY_POINT: + if (F->Point) + return (F->Point(ctx, (pcb_layer_t *) Ptr1, (pcb_poly_t *) Ptr2, (pcb_point_t *) Ptr3)); + break; + + case PCB_TYPE_VIA: + if (F->Via) + return (F->Via(ctx, (pcb_pin_t *) Ptr1)); + break; + + case PCB_TYPE_ELEMENT: + if (F->Element) + return (F->Element(ctx, (pcb_element_t *) Ptr1)); + break; + + case PCB_TYPE_SUBC: + if (F->subc) + return (F->subc(ctx, (pcb_subc_t *) Ptr1)); + break; + + case PCB_TYPE_PIN: + if (F->Pin) + return (F->Pin(ctx, (pcb_element_t *) Ptr1, (pcb_pin_t *) Ptr2)); + break; + + case PCB_TYPE_PAD: + if (F->Pad) + return (F->Pad(ctx, (pcb_element_t *) Ptr1, (pcb_pad_t *) Ptr2)); + break; + + case PCB_TYPE_PSTK: + if (F->padstack) + return (F->padstack(ctx, (pcb_pstk_t *)Ptr2)); + break; + + case PCB_TYPE_ELEMENT_NAME: + if (F->ElementName) + return (F->ElementName(ctx, (pcb_element_t *) Ptr1)); + break; + + case PCB_TYPE_RATLINE: + if (F->Rat) + return (F->Rat(ctx, (pcb_rat_t *) Ptr1)); + 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 changed = pcb_false; + + /* check lines */ + if (type & PCB_TYPE_LINE && F->Line) { + PCB_LINE_VISIBLE_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + 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_TYPE_ARC && F->Arc) { + PCB_ARC_VISIBLE_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, arc)) { + 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_TYPE_TEXT && F->Text) { + PCB_TEXT_ALL_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) && pcb_text_is_visible(PCB, layer, text)) { + 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_TYPE_POLY && F->Polygon) { + PCB_POLY_VISIBLE_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) { + 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_TYPE_SUBC && F->subc) { + PCB_SUBC_LOOP(data); + { + 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) { + if (pcb_selected_operation(pcb, subc->data, F, ctx, Reset, type)) + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + + /* elements silkscreen */ + if (type & PCB_TYPE_ELEMENT && pcb_silk_on(pcb) && F->Element) { + PCB_ELEMENT_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + if (Reset) { + pcb_undo_add_obj_to_flag(element); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, element); + } + F->Element(ctx, element); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + if (type & PCB_TYPE_ELEMENT_NAME && pcb_silk_on(pcb) && F->ElementName) { + PCB_ELEMENT_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element))) { + if (Reset) { + pcb_undo_add_obj_to_flag(&PCB_ELEM_TEXT_VISIBLE(PCB, element)); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element)); + } + F->ElementName(ctx, element); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + if (type & PCB_TYPE_PIN && pcb->PinOn && F->Pin) { + PCB_ELEMENT_LOOP(data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin)) { + if (Reset) { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, pin); + } + F->Pin(ctx, element, pin); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + + if (type & PCB_TYPE_PAD && pcb->PinOn && F->Pad) { + PCB_ELEMENT_LOOP(data); + { + PCB_PAD_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad)) { + if (Reset) { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, pad); + } + F->Pad(ctx, element, pad); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + + /* process vias and padstacks */ + if (type & PCB_TYPE_VIA && pcb->ViaOn && F->Via) { + PCB_VIA_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, via)) { + if (Reset) { + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, via); + } + F->Via(ctx, via); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + if (type & PCB_TYPE_PSTK && pcb->ViaOn && F->padstack) { + PCB_PADSTACK_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, padstack)) { + 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_TYPE_RATLINE && pcb->RatOn && F->Rat) { + PCB_RAT_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + 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(); + + return (changed); +} Index: tags/1.2.7/src/operation.h =================================================================== --- tags/1.2.7/src/operation.h (nonexistent) +++ tags/1.2.7/src/operation.h (revision 13657) @@ -0,0 +1,156 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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_bool bulk; /* don't draw if part of a bulk operation */ +} 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 *); + void *(*Via)(pcb_opctx_t *ctx, pcb_pin_t *); + void *(*Element)(pcb_opctx_t *ctx, pcb_element_t *); + void *(*ElementName)(pcb_opctx_t *ctx, pcb_element_t *); + void *(*Pin)(pcb_opctx_t *ctx, pcb_element_t *, pcb_pin_t *); + void *(*Pad)(pcb_opctx_t *ctx, pcb_element_t *, pcb_pad_t *); + 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); + +#endif Index: tags/1.2.7/src/paths.c =================================================================== --- tags/1.2.7/src/paths.c (nonexistent) +++ tags/1.2.7/src/paths.c (revision 13657) @@ -0,0 +1,278 @@ +/* + * 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. + * + */ + +/* 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 : "no_file_name"); + (*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); +} + +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; + const char *curr, *next; + + if (template == NULL) + return NULL; + + 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 s.array; + } + 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) { + 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) { + 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) { + 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 { + 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:; + 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) +{ + for (; numpaths > 0; numpaths--, in++, out++) + *out = pcb_strdup_subst_(*in, pcb_build_fn_cb, NULL, PCB_SUBST_ALL, extra_room); +} + +void pcb_path_resolve(const char *in, char **out, unsigned int extra_room) +{ + pcb_paths_resolve(&in, out, 1, extra_room); +} + +char *pcb_path_resolve_inplace(char *in, unsigned int extra_room) +{ + char *out; + pcb_path_resolve(in, &out, extra_room); + free(in); + return out; +} Index: tags/1.2.7/src/paths.h =================================================================== --- tags/1.2.7/src/paths.h (nonexistent) +++ tags/1.2.7/src/paths.h (revision 13657) @@ -0,0 +1,73 @@ +/* + * 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. + * + */ + +/* 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. */ +void pcb_path_resolve(const char *in, char **out, unsigned int extra_room); + +/* 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); + + +/* 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); + +/* Resolve all paths from a char *in[] into a freshly allocated char **out */ +#define pcb_paths_resolve_all(in, out, extra_room) \ +do { \ + int __numpath__ = sizeof(in) / sizeof(char *); \ + if (__numpath__ > 0) { \ + out = malloc(sizeof(char *) * __numpath__); \ + pcb_paths_resolve(in, out, __numpath__, extra_room); \ + } \ +} 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/1.2.7/src/pcb-conf.lht =================================================================== --- tags/1.2.7/src/pcb-conf.lht (nonexistent) +++ tags/1.2.7/src/pcb-conf.lht (revision 13657) @@ -0,0 +1,297 @@ +li:pcb-rnd-conf-v1 { + ha:overwrite { + ha:editor { + grid_unit = mil + grid = 25 mil + ha:increments_mm { + grid=0.1mm + grid_min=0.01mm + grid_max=1mm + size=0.2mm + size_min=0.01mm + size_max=0.5mm + line=0.1mm + line_min=0.005mm + line_max=9.5mm + clear=0.05mm + clear_min=0.005mm + clear_max=0.5mm + } + ha:increments_mil { + grid=5 mil + grid_min=1 mil + grid_max=25 mil + size=10 mil + size_min = 1 mil + size_max = 10 mil + line=5 mil + line_min = 0.5 mil + line_max = 10 mil + clear=2 mil + clear_min = 0.5 mil + clear_max = 10 mil + } + 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 + 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 + wireframe_draw = 0 + local_ref = 0 + check_planes = 0 + hide_names = 0 + description = 0 + name_on_pcb = 1 + enable_stroke = 0 + live_routing = 0 + beep_when_finished = 0 + click_time = 200 + 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 = 0 + } # editor + + ha:rc { + verbose = 0 + quiet = 0 + backup_interval = 60 + brave = {} +# font_command = {} +# file_command = {} +# file_path = {} + library_shell = {} + + emergency_name = {PCB.%ld.save} + emergency_format = {lihata} + backup_name = {PCB.%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 } + save_final_fallback_fmt = lihata + save_fp_fmt = mainline + } # rc + + ha:design { +# via_thickness = 0 +# via_drilling_hole = 0 +# line_thickness = 0 +# clearance = 0 +# max_width = 0 +# max_height = 0 +# alignment_distance = 0 +# bloat = 0 +# shrink = 0 +# min_wid = 0 +# min_slk = 0 +# min_drill = 0 +# min_ring = 0 + text_scale = 100 + text_font_id = 0 +# poly_isle_area = 0 +# li:default_layer_name = {layername1; layername2} +# background_image = {} +# fab_author = {} + groups = {} + routes = {} + paste_adjust = 0 + } # design + + ha:appearance { + rat_thickness = 0.25 mm + mark_size = 50 mil + layer_alpha = 0.7 + drill_alpha = 0.85 + + ha:loglevels { + debug_tag = {} + debug_popup = false + info_tag = {} + info_popup = false + warning_tag = {} + warning_popup = true + error_tag = {} + error_popup = true + } + ha:color { + black = {#000000} + white = {#ffffff} + background = {#e5e5e5} + crosshair = {#ff0000} + cross = {#cdcd00} + via = {#7f7f7f} + via_selected = {#00ffff} + pin = {#4d4d4d} + pin_selected = {#00ffff} + pin_name = {#ff0000} + element = {#000000} + element_nonetlist = {#777777} + subc = {#CC0000} + subc_nonetlist = {#551111} + subc_selected = {#00ffff} + padstackmark = {#CC0000} + rat = {#b8860b} + invisible_objects = {#cccccc} + invisible_mark = {#cccccc} + element_selected = {#00ffff} + rat_selected = {#00ffff} + connected = {#00ff00} + off_limit = {#cccccc} + 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}; + } + li:layer_selected = { + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; + {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; {#00ffff}; + {#00ffff}; + } + warn = {#ff8000} + mask = {#ff0000} + paste = {#cd00cd} + } + ha:pinout { +# name_length = 0 +# zoom = 0 + offset_x = 25400 + offset_y = 25400 + text_offset_x = 0.1 mm + text_offset_y = 0.1 mm + } + ha:messages { +# char_per_line = 0 + } +# ha:misc { +# volume = 0 +# } misc; + } # appearance; + + ha:plugins { + 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 + } + ha:import_mentor_sch { + li:map_search_paths = { + {./mentor_parts.map} + {$(rc.path.share)/mentor_parts.map} + } + } + ha:hid_gtk { + compact_horizontal = 1 + compact_vertical = 1 + use_command_window = 0 + history_size = 16 + 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 + } + } # plugins + + ha:utils { + ha:gsch2pcb-rnd { + remove_unfound_elements = 1 + quiet_mode = 0 + verbose = 0 + } + } # utils + } # main +} # root + Index: tags/1.2.7/src/pcb-menu-gtk.lht =================================================================== --- tags/1.2.7/src/pcb-menu-gtk.lht (nonexistent) +++ tags/1.2.7/src/pcb-menu-gtk.lht (revision 13657) @@ -0,0 +1,680 @@ +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 { + m=F + 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 = { m=S; a={Ctrls}; action=Save(Layout); tip=Saves current layout } + ha:Save Layout As... = { m=A; a={Shift Ctrls}; action=Save(LayoutAs); tip=Saves current layout into a new file } + - + ha:Import { + m=I + 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 element/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 { + m=E + 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:Element = { action=Attributes(Element) } + ha:Subcircuit = { action=Attributes(Subc) } + } + } + ha:Change flags { + li:submenu { + ha:Nonetlist = { a=Altn; action=ChangeNonetlist(Element) } + } + } + 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 { + m=V + 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 element name { + li:submenu { + ha:Description = { checked=ChkElementName(1); action=Display(Description); update_on={editor/description} } + ha:Reference Designator = { checked=ChkElementName(2); action=Display(NameOnPCB); update_on={editor/name_on_pcb} } + ha:Value = { checked=ChkElementName(3); action=Display(Value); update_on={editor/name_on_pcb} } + } + } + ha:Enable 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:Zoom In 20% = { m=Z; a=z; action=Zoom(-1.2) } + ha:Zoom Out 20% = { m=O; a=Shiftz; action=Zoom(+1.2) } + ha:More zooms and view changes { + li:submenu { + ha:Zoom Max = { m=M; 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 = { m=Z; li:action={Zoom(-1.2); Center()} } + ha:Zoom Out 20% and center= { m=O; 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 = { + m=S + 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:Require unique element names = { checked=editor/unique_names; action=conf(toggle, editor/unique_names, 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 = { + m=I + li:submenu { + ha:Center = { m=C; action=Import(setnewpoint,center) } + ha:Mark = { m=M; action=Import(setnewpoint,mark) } + ha:Crosshair = { m=h; action=Import(setnewpoint) } + - + ha:Set Dispersion = { m=D; action=Import(setdisperse) } + } + } + } + } #Settings + + ha:Select { + m=l + 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:Select by name { + li:submenu { + ha:All objects = { active=rc/have_regex; action=Select(ObjectByName) } + ha:Elements = { active=rc/have_regex; action=Select(ElementByName) } + ha:Pads = { active=rc/have_regex; action=Select(PadByName) } + ha:Pins = { active=rc/have_regex; action=Select(PinByName) } + ha:Text = { active=rc/have_regex; action=Select(TextByName) } + ha:Vias = { active=rc/have_regex; action=Select(ViaByName) } + } + } +#TODO: this is gtk-specific + ha:Advanced search and select= { action=DoWindows(search) } + - + ha:Auto-place selected elements = { a=Ctrlp; action=AutoPlaceSelected() } + ha:Disperse all elements/subcircuits = { action=DisperseElements(All) } + ha:Disperse selected elements/subcircuits= { action=DisperseElements(Selected) } + - + ha:Move selected elements 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 element = { action=Select(Convert) } + 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 objects { + li:submenu { + ha:Vias -10 mil = { action=ChangeDrillSize(SelectedVias,-10,mil) } + ha:Vias +10 mil = { action=ChangeDrillSize(SelectedVias,+10,mil) } + ha:Pins -10 mil = { action=ChangeDrillSize(SelectedPins,-10,mil) } + ha:Pins +10 mil = { action=ChangeDrillSize(SelectedPins,+10,mil) } + } + } + - + ha:Change square-flag of selected objects { + li:submenu { + ha:Elements = { action=ChangeSquare(SelectedElements) } + ha:Pins = { action=ChangeSquare(SelectedPins) } + } + } + ha:Cycle object being dragged = { a=x; action=CycleDrag() } + } + } # Select + + ha:Buffer { + m=B + 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 element = { action=PasteBuffer(Convert) } + ha:Convert buffer to subcircuit = { action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements/subcircuits to file = { action=Save(PasteBuffer) } + ha:Layer bindings... = { action=LayerBinding(buffer) } + - + ha:Select Buffer \#1 = { checked=ChkBuffer(1); m=1; a=Shift1; action=PasteBuffer(1); update_on={editor/buffer_number} } + ha:Select Buffer \#2 = { checked=ChkBuffer(2); m=2; a=Shift2; action=PasteBuffer(2); update_on={editor/buffer_number} } + ha:Select Buffer \#3 = { checked=ChkBuffer(3); m=3; a=Shift3; action=PasteBuffer(3); update_on={editor/buffer_number} } + ha:Select Buffer \#4 = { checked=ChkBuffer(4); m=4; a=Shift4; action=PasteBuffer(4); update_on={editor/buffer_number} } + ha:Select Buffer \#5 = { checked=ChkBuffer(5); m=5; a=Shift5; action=PasteBuffer(5); update_on={editor/buffer_number} } + } + } # Buffer + + ha:Connects = { + m=C + 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 { + m=P + li:submenu { + ha:Manage plugins... = { a=Altp; action=ManagePlugins() } + } + } # Plugins + + ha:Info = { + m=I + 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:ToggleHideName Object = { a=h; action=ToggleHideName(Object) } + ha:ToggleHideName SelectedElement = { a=Shifth; action=ToggleHideName(SelectedElements) } + ha:ChangeHole Object = { a=Ctrlh; action=ChangeHole(Object) } + 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:ChangeOctagon Object = { a=Ctrlo; action=ChangeOctagon(Object) } + ha:Polygon PreviousPoint = { a=p; action=Polygon(PreviousPoint) } + ha:Polygon Close = { a=Shiftp; action=Polygon(Close) } + ha:ChangeSquare Object = { a=q; action=ChangeSquare(ToggleObject) } + 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:Via Tool size +5 mil = { a=Shiftv; action=SetValue(ViaSize,+5,mil) } + ha:Via Tool size -5 mil = { a=Shift Ctrlv; action=SetValue(ViaSize,-5,mil) } + ha:Via Tool drill +5 mil = { a=Altv; action=SetValue(ViaDrillingHole,+5,mil) } + ha:Via Tool drill -5 mil = { a=Alt Shiftv; action=SetValue(ViaDrillingHole,-5,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 { + m=W + 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 element = { action=Select(Convert) } + ha:Auto place selected elements = { action=AutoPlaceSelected() } + ha:Autoroute selected elements = { action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + } + } + 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/1.2.7/src/pcb-menu-lesstif.lht =================================================================== --- tags/1.2.7/src/pcb-menu-lesstif.lht (nonexistent) +++ tags/1.2.7/src/pcb-menu-lesstif.lht (revision 13657) @@ -0,0 +1,537 @@ +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 = { m=S; a=Ctrls; action=Save(Layout) } + ha:Save layout as... = { m=A; 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 element/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 = { m=Q; 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 element-name... = { foreground=grey50; sensitive=false } + ha:Description = { checked=ChkElementName(1); action=Display(Description) } + ha:Reference Designator = { checked=ChkElementName(2); action=Display(NameOnPCB) } + ha:Value = { checked=ChkElementName(3); action=Display(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:Pinout shows number = { checked=editor/show_number; action=conf(toggle, editor/show_number, design) } + ha:Open pinout menu = { a=Shiftd; action=Display(Pinout) } + ha:Zoom { + li:submenu { + ha:Zoom In 2X = { action=Zoom(-2) } + ha:Zoom In 20% = { m=Z; a=z; action=Zoom(-1.2) } + ha:Zoom Out 20% = { m=O; a=Shiftz; action=Zoom(+1.2); } + ha:Zoom Out 2X = { action=Zoom(+2) } + ha:Zoom Max = { m=M; 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:Require unique element names = { checked=editor/unique_names; action=conf(toggle, editor/unique_names, 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 elements 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:Select by name = { foreground=grey50; sensitive=false } + ha:All objects = { active=rc/have_regex; action=Select(ObjectByName) } + ha:Elements = { active=rc/have_regex; action=Select(ElementByName) } + ha:Pads = { active=rc/have_regex; action=Select(PadByName) } + ha:Pins = { active=rc/have_regex; action=Select(PinByName) } + ha:Text Objects = { active=rc/have_regex; action=Select(TextByName) } + ha:Vias = { active=rc/have_regex; action=Select(ViaByName) } + - + ha:Auto-place selected elements = { a=Ctrlp; action=AutoPlaceSelected() } + ha:Disperse all elements/subcircuits = { action=DisperseElements(All) } + ha:Move selected elements 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 element = { action=Select(Convert) } + 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 objects = { foreground=grey50; sensitive=false } + ha:Vias -10 mil = { action=ChangeDrillSize(SelectedVias,-10,mil) } + ha:Vias +10 mil = { action=ChangeDrillSize(SelectedVias,+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); } + - + ha:Change square-flag of selected objects = { foreground=grey50; sensitive=false } + ha:Elements = { action=ChangeSquare(SelectedElements) } + ha:Pins = { action=ChangeSquare(SelectedPins) } + } + } # 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 element = { action=PasteBuffer(Convert) } + ha:Convert buffer to subcircuit = { action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements/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:ToggleHideName Object = { a=h; action=ToggleHideName(Object) } + ha:ToggleHideName SelectedElement = { a=Shifth; action=ToggleHideName(SelectedElements) } + ha:ChangeHole Object = { a=Ctrlh; action=ChangeHole(Object) } + 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:ChangeOctagon Object = { a=Ctrlo; action=ChangeOctagon(Object) } + ha:Polygon PreviousPoint = { a=p; action=Polygon(PreviousPoint) } + ha:Polygon Close = { a=Shiftp; action=Polygon(Close) } + ha:ChangeSquare Object = { a=q; action=ChangeSquare(Object) } + 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:Via Tool size +5 mil = { a=Shiftv; action=SetValue(ViaSize,+5,mil) } + ha:Via Tool size -5 mil = { a=Shift Ctrlv; action=SetValue(ViaSize,-5,mil) } + ha:Via Tool drill +5 mil = { a=Altv; action=SetValue(ViaDrillingHole,+5,mil) } + ha:Via Tool drill -5 mil = { a=Alt Shiftv; action=SetValue(ViaDrillingHole,-5,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/1.2.7/src/pcb-menu-mkey.lht =================================================================== --- tags/1.2.7/src/pcb-menu-mkey.lht (nonexistent) +++ tags/1.2.7/src/pcb-menu-mkey.lht (revision 13657) @@ -0,0 +1,641 @@ +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 = { Display(ToggleRubberbandMode); Mode(Save); Mode(Move); Mode(Notify) } + li:release-shift-ctrl = { Mode(Notify); Mode(Restore); Display(ToggleRubberbandMode) } + } + 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 { + m=F + 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 = { a={f;o}; action=Load(Layout); tip=Load a layout from a file } + - + ha:Save Layout = { m=S; li:a={{f;s}; {Ctrls};}; action=Save(Layout); tip=Saves current layout } + ha:Save Layout As... = { m=A; li:a={{f;a}; {Shift Ctrls};}; action=Save(LayoutAs); tip=Saves current layout into a new file } + - + ha:Import { + m=I + 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 element/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 = { li: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... = { a={f;p}; action=Print()} + ha:Export layout... = { a={f;i}; 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 = { li:a={{f;c}; {Ctrlq};}; action=Quit() } + } + } + + ha:Edit { + m=E + li:submenu { + ha:Undo last operation = { li:a={{e; Shiftu}; {Ctrlz}; {u};}; action=Undo() } + ha:Redo last undone operation = { li:a={{e; Shiftr}; {Ctrly}; {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(MoveSelected); 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 = { 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 name of { + ha:Change font on layout = { li:a={{e;f};} action=FontSel(Object) } + li:submenu { + ha:text on layout = { li:a={{e;x}; {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:Element = { action=Attributes(Element) } + ha:Subcircuit = { action=Attributes(Subc) } + } + } + ha:Change flags { + li:submenu { + ha:Nonetlist = { a=Altn; action=ChangeNonetlist(Element) } + } + } + 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 { + m=V + 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 = { li:a={{[};{Shiftg};}; action=SetValue(Grid,-5,mil) } + ha:Grid +5mil = { li: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) } } + 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) } } + 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) } } + 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) } } + - + 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) } } + 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) } } + 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) } } + } + } + ha:Realign grid = { action={ GetXY(Click to set the grid origin); Display(ToggleGrid) } } + - + ha:Displayed element name { + li:submenu { + ha:Description = { checked=ChkElementName(1); action=Display(Description); update_on={editor/description} } + ha:Reference Designator = { checked=ChkElementName(2); action=Display(NameOnPCB); update_on={editor/name_on_pcb} } + ha:Value = { checked=ChkElementName(3); action=Display(Value); update_on={editor/name_on_pcb} } + } + } + ha:Enable 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:Zoom In 20% = { m=Z; a=z; action=Zoom(-1.2) } + ha:Zoom Out 20% = { m=O; a=Shiftz; action=Zoom(+1.2) } + ha:More zooms and view changes { + li:submenu { + ha:Zoom Max = { li:a={{v;f}; {v;e};}; m=M; action=Zoom() } + ha:Zoom In 2X = { a={v;i}; action=Zoom(-2) } + ha:Zoom Out 2X = { a={v;o}; 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 = { m=Z; li:action={Zoom(-1.2); Center()} } + ha:Zoom Out 20% and center= { m=O; 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=EditLayerGroups() } + } + } + 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 = { + m=S + li:submenu { + ha:'All-direction' lines = { checked=editor/alldirection_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=enablemincut; action=Display(ToggleMinCut) } + 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:Require unique element names = { checked=editor/unique_names; action=conf(toggle, editor/unique_names, 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:Vendor drill mapping = { checked=plugins/vendor/enable; action=conf(toggle, plugins/vendor/enable, design) } + ha:Import New Elements at = { + m=I + li:submenu { + ha:Center = { m=C; action=Import(setnewpoint,center) } + ha:Mark = { m=M; action=Import(setnewpoint,mark) } + ha:Crosshair = { m=h; action=Import(setnewpoint) } + - + ha:Set Dispersion = { m=D; action=Import(setdisperse) } + } + } + } + } #Settings + + ha:Select { + m=l + 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:Select by name { + li:submenu { + ha:All objects = { active=rc/have_regex; action=Select(ObjectByName) } + ha:Elements = { active=rc/have_regex; action=Select(ElementByName) } + ha:Pads = { active=rc/have_regex; action=Select(PadByName) } + ha:Pins = { active=rc/have_regex; action=Select(PinByName) } + ha:Text = { active=rc/have_regex; action=Select(TextByName) } + ha:Vias = { active=rc/have_regex; action=Select(ViaByName) } + } + } + - + ha:Auto-place selected elements = { a=Ctrlp; action=AutoPlaceSelected() } + ha:Disperse all elements/subcircuits = { action=DisperseElements(All) } + ha:Disperse selected elements/subcircuits= { action=DisperseElements(Selected) } + - + ha:Move selected elements 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 element = { action=Select(Convert) } + 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 { + 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 objects { + li:submenu { + ha:Vias -10 mil = { action=ChangeDrillSize(SelectedVias,-10,mil) } + ha:Vias +10 mil = { action=ChangeDrillSize(SelectedVias,+10,mil) } + ha:Pins -10 mil = { action=ChangeDrillSize(SelectedPins,-10,mil) } + ha:Pins +10 mil = { action=ChangeDrillSize(SelectedPins,+10,mil) } + } + } + - + ha:Change square-flag of selected objects { + li:submenu { + ha:Elements = { action=ChangeSquare(SelectedElements) } + ha:Pins = { action=ChangeSquare(SelectedPins) } + } + } + ha:Cycle object being dragged = { a=x; action=CycleDrag() } + } + } # Select + + ha:Buffer { + m=B + 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={{e; r}; {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) = { a={e; i}; 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 element = { action=PasteBuffer(Convert) } + ha:Convert buffer to subcircuit = { action=PasteBuffer(ConvertSubc) } + ha:Convert buffer to padstack = { li:action={PadstackConvert(buffer); Mode(PasteBuffer);} } + ha:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements/subcircuits to file = { action=Save(PasteBuffer) } + ha:Layer bindings... = { action=LayerBinding(buffer) } + - + ha:Select Buffer \#1 = { checked=ChkBuffer(1); m=1; a=Shift1; action=PasteBuffer(1); update_on={editor/buffer_number} } + ha:Select Buffer \#2 = { checked=ChkBuffer(2); m=2; a=Shift2; action=PasteBuffer(2); update_on={editor/buffer_number} } + ha:Select Buffer \#3 = { checked=ChkBuffer(3); m=3; a=Shift3; action=PasteBuffer(3); update_on={editor/buffer_number} } + ha:Select Buffer \#4 = { checked=ChkBuffer(4); m=4; a=Shift4; action=PasteBuffer(4); update_on={editor/buffer_number} } + ha:Select Buffer \#5 = { checked=ChkBuffer(5); m=5; a=Shift5; action=PasteBuffer(5); update_on={editor/buffer_number} } + } + } # Buffer + + ha:Connects = { + m=C + 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 = { 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 { + m=P + li:submenu { + ha:Manage plugins... = { a=Altp; action=ManagePlugins() } + } + } # Plugins + + ha:Info = { + m=I + 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 = { li:a={{e;d};{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 = { action=SetSame() } + ha:Flip Object = { a=b; action=Flip(Object) } + ha:Find Connections = { li:action={Connection(Reset); Connection(Find)} } + ha:ToggleHideName Object = { action=ToggleHideName(Object) } + ha:ToggleHideName SelectedElement = { a=Shifth; action=ToggleHideName(SelectedElements) } + ha:ChangeHole Object = { a=Ctrlh; action=ChangeHole(Object) } + 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:ChangeOctagon Object = { a=Ctrlo; action=ChangeOctagon(Object) } + ha:Polygon PreviousPoint = { a=p; action=Polygon(PreviousPoint) } + ha:Polygon Close = { a=Shiftp; action=Polygon(Close) } + ha:ChangeSquare Object = { a=q; action=ChangeSquare(ToggleObject) } + 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:Via Tool size +5 mil = { a=Shiftv; action=SetValue(ViaSize,+5,mil) } + ha:Via Tool size -5 mil = { a=Shift Ctrlv; action=SetValue(ViaSize,-5,mil) } + ha:Via Tool drill +5 mil = { a=Altv; action=SetValue(ViaDrillingHole,+5,mil) } + ha:Via Tool drill -5 mil = { a=Alt Shiftv; action=SetValue(ViaDrillingHole,-5,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 = { li:action={Mode(Save); Mode(Arrow); Mode(Notify)} } + ha:Temp Arrow OFF = { 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 { + m=W + li:submenu { + ha:Library = { a={a;c} 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... = { a={h;a}; 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 element = { action=Select(Convert) } + ha:Auto place selected elements = { action=AutoPlaceSelected() } + ha:Autoroute selected elements = { action=AutoRoute(SelectedRats) } + ha:Rip up selected auto-routed tracks = { action=RipUp(Selected) } + } + } + 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); li:a={{a;n}; {a;l}; {F2};}; action=Mode(Line); update_on={editor/mode} } + ha:Arc = { checked=ChkMode(arc); li:a={{a;r}; {F3};}; action=Mode(Arc); update_on={editor/mode} } + ha:Text = { checked=ChkMode(text); li:a={{a;t}; {F4};}; action=Mode(Text); update_on={editor/mode} } + ha:Rectangle = { checked=ChkMode(rectangle); li:a={{a;p}; {a;v}; {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); li:a={{e;l}; {e;Shiftl}; {F12};}; action=Mode(Lock); update_on={editor/mode} } + ha:Cancel = { a=Escape; action=Mode(Escape); } + } + } + } + } # popup1 + } # popups +} # root Index: tags/1.2.7/src/pcb-printf.c =================================================================== --- tags/1.2.7/src/pcb-printf.c (nonexistent) +++ tags/1.2.7/src/pcb-printf.c (revision 13657) @@ -0,0 +1,912 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ + +/*! \file + * \brief Implementation of printf wrapper to output pcb coords and angles + * \par Description + * 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" +#include "compat_nls.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 */ +#define sprintf_lc_safe(is_file_mode, out, fmt, val) \ +do { \ + if (is_file_mode) { \ + pcb_setlocale(LC_ALL, "C"); \ + sprintf(out, fmt, val); \ + pcb_setlocale(LC_ALL, ""); \ + } \ + else \ + 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; +} + + +/* \brief Internal coord-to-string converter for pcb-printf + * \par Function Description + * 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. + * + * \param [in] dest Append the output to this dynamic string + * \param [in] coord Array of coords to convert + * \param [in] n_coords Number of coords in array + * \param [in] printf_spec printf sub-specifier to use with %f + * \param [in] e_allow Bitmap of units the function may use + * \param [in] 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; + 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); + v = v * unit->scale_factor; + + /* 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 = v; + *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; +} + +/* \brief Main low level pcb-printf function + * \par Function Description + * 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. + * + * \param [in] string Append anything new at the end of this dynamic string (must be initialized before the call) + * \param [in] fmt Format specifier + * \param [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 '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; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a string + * + * \param [in] string Pointer to string to output into + * \param [in] fmt Format specifier + * + * \return The length of the written string + */ +int pcb_sprintf(char *string, const char *fmt, ...) +{ + gds_t str; + va_list args; + + gds_init(&str); + 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; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a string with a size limit + * + * \param [in] string Pointer to string to output into + * \param [in] len Maximum length + * \param [in] fmt Format specifier + * + * \return The length of the written string + */ +int pcb_snprintf(char *string, size_t len, const char *fmt, ...) +{ + gds_t str; + va_list args; + + gds_init(&str); + 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; + + gds_init(&str); + + str.array = string; + str.alloced = len; + str.no_realloc = 1; + + pcb_append_vprintf(&str, fmt, args); + + return str.used; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a file + * + * \param [in] fh File to output to + * \param [in] fmt Format specifier + * + * \return The length of the written string + */ +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; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a file + * + * \param [in] fh File to output to + * \param [in] fmt Format specifier + * \param [in] args Arguments to specifier + * + * \return The length of the written string + */ +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; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to stdout + * + * \param [in] fmt Format specifier + * + * \return The length of the written string + */ +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; +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a newly allocated string + * + * \param [in] fmt Format specifier + * + * \return The newly allocated string. Must be freed with free. + */ +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 */ +} + +/* \brief Wrapper for pcb_append_vprintf that outputs to a string + * + * \param [in] string Pointer to string to output into + * \param [in] fmt Format specifier + * + * \return return the new string; must be free()'d later + */ +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 */ +} + + +/* \brief Wrapper for pcb_append_vprintf that appends to a string using vararg API + * + * \param [in] str Existing dynamic string + * \param [in] fmt Format specifier + * + * \return 0 on success + */ +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/1.2.7/src/pcb-printf.h =================================================================== --- tags/1.2.7/src/pcb-printf.h (nonexistent) +++ tags/1.2.7/src/pcb-printf.h (revision 13657) @@ -0,0 +1,151 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 + * %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 + * %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" (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 = 0xff +} pcb_strdup_subst_t; + +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/1.2.7/src/pcb_bool.c =================================================================== --- tags/1.2.7/src/pcb_bool.c (nonexistent) +++ tags/1.2.7/src/pcb_bool.c (revision 13657) @@ -0,0 +1,34 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/pcb_bool.h =================================================================== --- tags/1.2.7/src/pcb_bool.h (nonexistent) +++ tags/1.2.7/src/pcb_bool.h (revision 13657) @@ -0,0 +1,57 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/pcb_minuid.c =================================================================== --- tags/1.2.7/src/pcb_minuid.c (nonexistent) +++ tags/1.2.7/src/pcb_minuid.c (revision 13657) @@ -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/1.2.7/src/pcb_minuid.h =================================================================== --- tags/1.2.7/src/pcb_minuid.h (nonexistent) +++ tags/1.2.7/src/pcb_minuid.h (revision 13657) @@ -0,0 +1,4 @@ +#include +extern minuid_session_t pcb_minuid; + +void pcb_minuid_init(void); Index: tags/1.2.7/src/plug_footprint.c =================================================================== --- tags/1.2.7/src/plug_footprint.c (nonexistent) +++ tags/1.2.7/src/plug_footprint.c (revision 13657) @@ -0,0 +1,453 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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" + +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; + 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) +{ + FILE *res = NULL; + PCB_HOOK_CALL(pcb_plug_fp_t, pcb_plug_fp_chain, fp_fopen, res, != NULL, (self, path, name, fctx)); + 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/1.2.7/src/plug_footprint.h =================================================================== --- tags/1.2.7/src/plug_footprint.h (nonexistent) +++ tags/1.2.7/src/plug_footprint.h (revision 13657) @@ -0,0 +1,91 @@ +#ifndef PCB_PLUG_FOOTPRINT_H +#define PCB_PLUG_FOOTPRINT_H + +#include +#include "vtlibrary.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); +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, 0 if file element. + 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 *********************************/ +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. + */ + FILE *(*fp_fopen)(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx); + +/* 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/1.2.7/src/plug_footprint_act.c =================================================================== --- tags/1.2.7/src/plug_footprint_act.c (nonexistent) +++ tags/1.2.7/src/plug_footprint_act.c (revision 13657) @@ -0,0 +1,70 @@ +/* + * 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. + * + */ + +#include "config.h" +#include "hid.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 int pcb_act_fp_rehash(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_fplibrary_t *l; + + if (argc == 0) { + pcb_fp_rehash(NULL); + return 0; + } + + l = pcb_fp_lib_search(&pcb_library, argv[0]); + if (l == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't find library path %s\n", argv[0]); + return 1; + } + + if (l->type != LIB_DIR) { + pcb_message(PCB_MSG_ERROR, "Library path %s is not a directory\n", argv[0]); + return 1; + } + + 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", argv[0]); + return 1; + } + + if (pcb_fp_rehash(l) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to rehash %s\n", argv[0]); + return 1; + } + return 0; +} + + +pcb_hid_action_t conf_plug_footprint_list[] = { + {"fp_rehash", 0, pcb_act_fp_rehash, + pcb_acth_fp_rehash, pcb_acts_fp_rehash} +}; + +PCB_REGISTER_ACTIONS(conf_plug_footprint_list, NULL) Index: tags/1.2.7/src/plug_import.c =================================================================== --- tags/1.2.7/src/plug_import.c (nonexistent) +++ tags/1.2.7/src/plug_import.c (revision 13657) @@ -0,0 +1,118 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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) + + 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); +} Index: tags/1.2.7/src/plug_import.h =================================================================== --- tags/1.2.7/src/plug_import.h (nonexistent) +++ tags/1.2.7/src/plug_import.h (revision 13657) @@ -0,0 +1,62 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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; + +/********** hook wrappers **********/ +int pcb_import(char *filename, unsigned int aspect); +int pcb_import_netlist(char *); + + +#endif Index: tags/1.2.7/src/plug_io.c =================================================================== --- tags/1.2.7/src/plug_io.c (nonexistent) +++ tags/1.2.7/src/plug_io.c (revision 13657) @@ -0,0 +1,1027 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* 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 */ + +#warning TODO: do not hardwire this, make a function to decide +#define DEFAULT_FMT "pcb" + +#include "config.h" +#include "conf_core.h" + +#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 "hid_actions.h" +#include "hid_flags.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_nls.h" +#include "compat_lrealpath.h" +#include "layer_vis.h" +#include "safe_fs.h" + +/* for opendir */ +#include "compat_inc.h" + +pcb_plug_io_t *pcb_plug_io_chain = NULL; +int pcb_io_err_inhibit = 0; + +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"); +} + +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 */ + FILE *ft; + int accept_total = 0; + + ft = pcb_fopen(Filename, "r"); + 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 (load_settings) + pcb_event(PCB_EVENT_LOAD_PRE, "s", Filename); + + Ptr->Data->loader = NULL; + + len = pcb_find_io(available, sizeof(available)/sizeof(available[0]), PCB_IOT_PCB, 0, fmt); + if (fmt != NULL) { + /* explicit format */ + for(n = 0; n < len; n++) { + if (available[n].plug->parse_pcb != 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); + fclose(ft); + 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_pcb == NULL) || (available[n].plug->test_parse_pcb(available[n].plug, Ptr, Filename, ft))) { + accepts[n] = 1; + accept_total++; + } + else + accepts[n] = 0; + rewind(ft); + } + } + } + fclose(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; + } + + /* 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); + + plug_io_err(res, "load pcb", Filename); + return res; +} + +int pcb_parse_element(pcb_data_t *Ptr, const char *name) +{ + int res = -1; + + Ptr->loader = NULL; + PCB_HOOK_CALL_DO(pcb_plug_io_t, pcb_plug_io_chain, parse_element, res, == 0, (self, Ptr, name), Ptr->loader = self); + + plug_io_err(res, "load element", name); + 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_element_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_element != NULL)) + res = p->write_element(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); + + 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_CLAMP(PCB->CursorX, 0, PCB->MaxWidth); + pcb_crosshair.Y = PCB_CLAMP(PCB->CursorY, 0, PCB->MaxHeight); + + /* 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_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_sort_netlist(); + 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. */ + if (pcb_hid_get_flag("GetStyle()") < 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_gui->log("Loading file %s took %f seconds of CPU time\n", new_filename, elapsed); +#endif + + 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) +/* --------------------------------------------------------------------------- + * some local identifiers for OS without an atexit() call + */ +static char *TMPFilename = NULL; +#endif + +/* --------------------------------------------------------------------------- + * Flag helper functions + */ + +#define F2S(OBJ, TYPE) pcb_strflg_f2s((OBJ)->Flags, TYPE) + +/* --------------------------------------------------------------------------- */ + +static int string_cmp(const char *a, const char *b) +{ + while (*a && *b) { + if (isdigit((int) *a) && isdigit((int) *b)) { + int ia = atoi(a); + int ib = atoi(b); + if (ia != ib) + return ia - ib; + while (isdigit((int) *a) && *(a + 1)) + a++; + while (isdigit((int) *b) && *(b + 1)) + b++; + } + else if (tolower((int) *a) != tolower((int) *b)) + return tolower((int) *a) - tolower((int) *b); + a++; + b++; + } + if (*a) + return 1; + if (*b) + return -1; + return 0; +} + +static int netlist_sort_offset = 0; + +static int netlist_sort(const void *va, const void *vb) +{ + const pcb_lib_menu_t *am = (const pcb_lib_menu_t *) va; + const pcb_lib_menu_t *bm = (const pcb_lib_menu_t *) vb; + const char *a = am->Name; + const char *b = bm->Name; + if (*a == '~') + a++; + if (*b == '~') + b++; + return string_cmp(a, b); +} + +static int netnode_sort(const void *va, const void *vb) +{ + const pcb_lib_entry_t *am = (const pcb_lib_entry_t *) va; + const pcb_lib_entry_t *bm = (const pcb_lib_entry_t *) vb; + const char *a = am->ListEntry; + const char *b = bm->ListEntry; + return string_cmp(a, b); +} + +void pcb_library_sort(pcb_lib_t *lib) +{ + int i; + qsort(lib->Menu, lib->MenuN, sizeof(lib->Menu[0]), netlist_sort); + for (i = 0; i < lib->MenuN; i++) + qsort(lib->Menu[i].Entry, lib->Menu[i].EntryN, sizeof(lib->Menu[i].Entry[0]), netnode_sort); +} + +void pcb_sort_netlist() +{ + netlist_sort_offset = 2; + pcb_library_sort(&(PCB->NetlistLib[PCB_NETLIST_INPUT])); + netlist_sort_offset = 0; +} + +/* --------------------------------------------------------------------------- + * opens a file and check if it exists + */ +FILE *pcb_check_and_open_file(const char *Filename, pcb_bool Confirm, pcb_bool AllButton, pcb_bool * WasAllButton, pcb_bool * WasCancelButton) +{ + FILE *fp = NULL; + struct stat buffer; + char message[PCB_PATH_MAX + 80]; + int response; + + if (Filename && *Filename) { + if (!stat(Filename, &buffer) && Confirm) { + sprintf(message, _("File '%s' exists, use anyway?"), Filename); + if (WasAllButton) + *WasAllButton = pcb_false; + if (WasCancelButton) + *WasCancelButton = pcb_false; + if (AllButton) + response = pcb_gui->confirm_dialog(message, "Cancel", "Ok", AllButton ? "Sequence OK" : 0); + else + response = pcb_gui->confirm_dialog(message, "Cancel", "Ok", "Sequence OK"); + + switch (response) { + case 2: + if (WasAllButton) + *WasAllButton = pcb_true; + break; + case 0: + if (WasCancelButton) + *WasCancelButton = pcb_true; + } + } + if ((fp = pcb_fopen(Filename, "w")) == NULL) + pcb_open_error_message(Filename); + } + return (fp); +} + +/* --------------------------------------------------------------------------- + * opens a file for saving connection data + */ +FILE *pcb_open_connection_file(void) +{ + char *fname; + FILE *fp; + static char *default_file = NULL; + pcb_bool result; /* not used */ + + /* CheckAndOpenFile deals with the case where fname already exists */ + fname = pcb_gui->fileselect(_("Save Connection Data As ..."), + _("Choose a file to save all connection data to."), default_file, ".net", "connection_data", 0); + if (fname == NULL) + return NULL; + + if (default_file != NULL) { + free(default_file); + default_file = NULL; + } + + if (fname && *fname) + default_file = pcb_strdup(fname); + + fp = pcb_check_and_open_file(fname, pcb_true, pcb_false, &result, NULL); + free(fname); + + return fp; +} + +/* --------------------------------------------------------------------------- + * save elements in the current buffer + */ +int pcb_save_buffer_elements(const char *Filename, const char *fmt) +{ + int result; + + if (PCB_SWAP_IDENT) + pcb_buffers_flip_side(PCB); + result = pcb_write_pipe(Filename, pcb_false, fmt, pcb_true); + if (PCB_SWAP_IDENT) + pcb_buffers_flip_side(PCB); + return (result); +} + +/* --------------------------------------------------------------------------- + * save PCB + */ +int pcb_save_pcb(const char *file, const char *fmt) +{ + int retcode; + + if (pcb_gui->notify_save_pcb == NULL) + return pcb_write_pipe(file, pcb_true, fmt, pcb_false); + + 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); + + return retcode; +} + + +/* --------------------------------------------------------------------------- + * Load PCB + */ +int pcb_load_pcb(const char *file, const char *fmt, pcb_bool require_font, int how) +{ + return real_load_pcb(file, fmt, pcb_false, require_font, how); +} + +/* --------------------------------------------------------------------------- + * Revert PCB + */ +int pcb_revert_pcb(void) +{ + return real_load_pcb(PCB->Filename, NULL, pcb_true, pcb_true, 1); +} + +/* --------------------------------------------------------------------------- + * writes the quoted string created by another subroutine + */ +void pcb_print_quoted_string(FILE * FP, const char *S) +{ + const char *start; + + fputc('"', FP); + 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); + + fputc('"', FP); +} + +/* --------------------------------------------------------------------------- + * saves the layout in a temporary file + * 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_FMT : conf_core.rc.emergency_name; + 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()' + * just makes sure that the routine 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; +} + +/* ---------------------------------------------------------------------- + * Callback for the 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); +} + +/* --------------------------------------------------------------------------- + * creates backup file. The default is to use the pcb file name with + * a "-" appended (like "foo.pcb-") and if we don't have a pcb file name + * then use the template in conf_core.rc.backup_name + */ +void pcb_backup(void) +{ + char *filename = NULL; + const char *fmt = NULL; + + if (PCB && PCB->Filename) { + filename = (char *) malloc(sizeof(char) * (strlen(PCB->Filename) + 2)); + if (filename == NULL) { + fprintf(stderr, "pcb_backup(): malloc failed\n"); + exit(1); + } + sprintf(filename, "%s-", PCB->Filename); + } + else { + /* conf_core.rc.backup_name has %.8i which will be replaced by the process ID */ + 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; + pcb_write_pcb_file(filename, pcb_true, fmt, pcb_true, pcb_false); + free(filename); +} + +#if !defined(HAS_ATEXIT) +/* --------------------------------------------------------------------------- + * makes a temporary copy of the data. This is useful for systems which + * doesn't support calling functions on exit. We use this to save the data + * before LEX and YACC functions are called because they are able to abort + * the program. + */ +void pcb_tmp_data_save(void) +{ + char *fn = pcb_build_fn(conf_core.rc.emergency_name); + pcb_write_pcb_file(fn, pcb_true, NULL, pcb_true, pcb_false); + if (TMPFilename != NULL) + free(TMPFilename); + TMPFilename = fn; +} + +/* --------------------------------------------------------------------------- + * removes the temporary copy of the data file + */ +void pcb_tmp_data_remove(void) +{ + if (TMPFilename != NULL) + unlink(TMPFilename); +} +#endif + +/* 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_element_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); +} + +/* --------------------------------------------------------------------------- + * writes PCB to file + */ +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); + + if (!pcb_conf_cmd_is_safe(rc.save_command, &save_cmd, 1)) + return -1; + + /* 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; + } + } +} + +void pcb_io_uninit(void) +{ + free(last_design_dir); + last_design_dir = NULL; +} Index: tags/1.2.7/src/plug_io.h =================================================================== --- tags/1.2.7/src/plug_io.h (nonexistent) +++ tags/1.2.7/src/plug_io.h (revision 13657) @@ -0,0 +1,186 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_PLUG_IO_H +#define PCB_PLUG_IO_H + +#include "library.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 board 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)(pcb_plug_io_t *ctx, pcb_board_t *Ptr, 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_element)(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_element)(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_element(pcb_data_t *Ptr, const char *name); +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_element_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 **********/ +FILE *pcb_check_and_open_file(const char *, pcb_bool, pcb_bool, pcb_bool *, pcb_bool *); +FILE *pcb_open_connection_file(void); +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_sort_netlist(void); +void pcb_print_quoted_string(FILE *, const char *); +void pcb_library_sort(pcb_lib_t *lib); +void pcb_set_some_route_style(); +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); + +#ifndef HAS_ATEXIT +void pcb_tmp_data_save(void); +void pcb_tmp_data_remove(void); +#endif + +/********** 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); + +void pcb_io_uninit(void); + +#endif Index: tags/1.2.7/src/plugins.c =================================================================== --- tags/1.2.7/src/plugins.c (nonexistent) +++ tags/1.2.7/src/plugins.c (revision 13657) @@ -0,0 +1,117 @@ +/* + * 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. + * + */ + +#include +#include +#include "plugins.h" + +/* for the action */ +#include "config.h" +#include "genvector/gds_char.h" +#include "compat_misc.h" +#include "hid.h" + +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; +} + + +/* ---------------------------------------------------------------- */ +static const char pcb_acts_ManagePlugins[] = "ManagePlugins()\n"; + +static const char pcb_acth_ManagePlugins[] = "Manage plugins dialog."; + +static int pcb_act_ManagePlugins(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pup_plugin_t *p; + int nump = 0, numb = 0; + gds_t str; + + 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_gui->report_dialog("Manage plugins", str.array); + gds_uninit(&str); + return 0; +} + + +pcb_hid_action_t plugins_action_list[] = { + {"ManagePlugins", 0, pcb_act_ManagePlugins, + pcb_acth_ManagePlugins, pcb_acts_ManagePlugins} +}; + +PCB_REGISTER_ACTIONS(plugins_action_list, NULL) Index: tags/1.2.7/src/plugins.h =================================================================== --- tags/1.2.7/src/plugins.h (nonexistent) +++ tags/1.2.7/src/plugins.h (revision 13657) @@ -0,0 +1,87 @@ +/* + * 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. + * + */ + +#ifndef PCB_RND_PLUGINS_H +#define PCB_RND_PLUGINS_H + +#include +#include + +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); \ + for(__n__ = chain; __n__ != NULL; __n__ = __n__->next) { \ + if ((__n__ == __h__) && (__prev__ != NULL)) \ + __prev__->next = __n__->next; \ + __prev__ = __n__; \ + } \ + if (chain == __n__) \ + chain = chain->next; \ +} while(0) + +#endif Index: tags/1.2.7/src/polyarea.h =================================================================== --- tags/1.2.7/src/polyarea.h (nonexistent) +++ tags/1.2.7/src/polyarea.h (revision 13657) @@ -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; + } 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); + +/**********************************************************************/ + +typedef struct pcb_polyarea_s pcb_polyarea_t; +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/1.2.7/src/polygon.c =================================================================== --- tags/1.2.7/src/polygon.c (nonexistent) +++ tags/1.2.7/src/polygon.c (revision 13657) @@ -0,0 +1,2339 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 "compat_nls.h" +#include "obj_all.h" +#include "obj_poly_draw.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); + +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_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 < PCB->IsleArea) { + 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_pline_t *contour = NULL; + pcb_polyarea_t *np = NULL; + pcb_cardinal_t n; + pcb_vector_t v; + int hole = 0; + + if ((np = pcb_polyarea_create()) == 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)); + + pcb_polyarea_contour_include(np, contour); + contour = NULL; + assert(pcb_poly_valid(np)); + + hole++; + } + } + return biggest(np); +} + +pcb_polyarea_t *pcb_poly_from_poly(pcb_poly_t * p) +{ + return original_poly(p); +} + +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); +} + +/* set up x and y multiplier for an octa poly, depending on square pin style */ +#warning padstack TODO: move this out to lib_compat_helper when removing pinvias +void pcb_poly_square_pin_factors(int style, double *xm, double *ym) +{ + int i; + const double factor = 2.0; + + /* reset multipliers */ + for (i = 0; i < 8; i++) { + xm[i] = 1; + ym[i] = 1; + } + + style--; + if (style & 1) + xm[0] = xm[1] = xm[6] = xm[7] = factor; + if (style & 2) + xm[2] = xm[3] = xm[4] = xm[5] = factor; + if (style & 4) + ym[4] = ym[5] = ym[6] = ym[7] = factor; + if (style & 8) + ym[0] = ym[1] = ym[2] = ym[3] = factor; +} + + +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); + +#warning 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; +} + +/* make a rounded-corner rectangle */ +pcb_polyarea_t *SquarePadPoly(pcb_pad_t * pad, pcb_coord_t clear) +{ + pcb_pline_t *contour = NULL; + pcb_polyarea_t *np = NULL; + pcb_vector_t v; + double d; + double tx, ty; + double cx, cy; + pcb_pad_t _t = *pad, *t = &_t; + pcb_pad_t _c = *pad, *c = &_c; + int halfthick = (pad->Thickness + 1) / 2; + int halfclear = (clear + 1) / 2; + + d = sqrt(PCB_SQUARE(pad->Point1.X - pad->Point2.X) + PCB_SQUARE(pad->Point1.Y - pad->Point2.Y)); + if (d != 0) { + double a = halfthick / d; + tx = (t->Point1.Y - t->Point2.Y) * a; + ty = (t->Point2.X - t->Point1.X) * a; + a = halfclear / d; + cx = (c->Point1.Y - c->Point2.Y) * a; + cy = (c->Point2.X - c->Point1.X) * a; + + t->Point1.X -= ty; + t->Point1.Y += tx; + t->Point2.X += ty; + t->Point2.Y -= tx; + c->Point1.X -= cy; + c->Point1.Y += cx; + c->Point2.X += cy; + c->Point2.Y -= cx; + } + else { + tx = halfthick; + ty = 0; + cx = halfclear; + cy = 0; + + t->Point1.Y += tx; + t->Point2.Y -= tx; + c->Point1.Y += cx; + c->Point2.Y -= cx; + } + + v[0] = c->Point1.X - tx; + v[1] = c->Point1.Y - ty; + if ((contour = pcb_poly_contour_new(v)) == NULL) + return 0; + pcb_poly_frac_circle_end(contour, (t->Point1.X - tx), (t->Point1.Y - ty), v, 4); + + v[0] = t->Point2.X - cx; + v[1] = t->Point2.Y - cy; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, (t->Point2.X - tx), (t->Point2.Y - ty), v, 4); + + v[0] = c->Point2.X + tx; + v[1] = c->Point2.Y + ty; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, (t->Point2.X + tx), (t->Point2.Y + ty), v, 4); + + v[0] = t->Point1.X + cx; + v[1] = t->Point1.Y + cy; + pcb_poly_vertex_include(contour->head.prev, pcb_poly_node_create(v)); + pcb_poly_frac_circle_end(contour, (t->Point1.X + tx), (t->Point1.Y + ty), v, 4); + + /* 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); +} + +/* create a polygon of the pin clearance */ +pcb_polyarea_t *pcb_poly_from_pin(pcb_pin_t * pin, pcb_coord_t thick, pcb_coord_t clear) +{ + int size; + + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) { + if (PCB_FLAG_SQUARE_GET(pin) <= 1) { + size = (thick + 1) / 2; + return RoundRect(pin->X - size, pin->X + size, pin->Y - size, pin->Y + size, (clear + 1) / 2); + } + else { + size = (thick + clear + 1) / 2; + return pcb_poly_from_octagon(pin->X, pin->Y, size + size, PCB_FLAG_SQUARE_GET(pin)); + } + + } + else { + size = (thick + clear + 1) / 2; + if (PCB_FLAG_TEST(PCB_FLAG_OCTAGON, pin)) { + if (PCB_FLAG_SQUARE_GET(pin) <= 1) + size /= 2; + return pcb_poly_from_octagon(pin->X, pin->Y, size + size, PCB_FLAG_SQUARE_GET(pin)); + } + } + return pcb_poly_from_circle(pin->X, pin->Y, size); +} + +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); +} + +/* return the clearance polygon for a pin */ +static pcb_polyarea_t *pin_clearance_poly(pcb_cardinal_t layernum, pcb_board_t *pcb, pcb_pin_t * pin) +{ + pcb_polyarea_t *np; + if (PCB_FLAG_THERM_TEST(layernum, pin)) + np = pcb_thermal_area_pin(pcb, pin, layernum); + else + np = pcb_poly_from_pin(pin, PIN_SIZE(pin), pin->Clearance); + return np; +} + +/* remove the pin clearance from the polygon */ +static int SubtractPin(pcb_data_t * d, pcb_pin_t * pin, pcb_layer_t * l, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + pcb_layer_id_t i; + + if (pin->Clearance == 0) + return 0; + i = pcb_layer_id(d, l); + np = pin_clearance_poly(i, pcb_data_get_top(d), pin); + + if (PCB_FLAG_THERM_TEST(i, pin)) { + if (!np) + return 0; + } + else { + if (!np) + return -1; + } + + return Subtract(np, p, pcb_true); +} + +/* 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 + PCB->Bloat, b->X2 - PCB->Bloat, b->Y1 + PCB->Bloat, b->Y2 - PCB->Bloat, PCB->Bloat))) + return -1; + return Subtract(np, p, pcb_true); +} + +static int SubtractPad(pcb_pad_t * pad, pcb_poly_t * p) +{ + pcb_polyarea_t *np = NULL; + + if (pad->Clearance == 0) + return 0; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pad)) { + if (!(np = SquarePadPoly(pad, pad->Thickness + pad->Clearance))) + return -1; + } + else { + if (!(np = pcb_poly_from_line((pcb_line_t *) pad, pad->Thickness + pad->Clearance))) + 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 pcb_r_dir_t pin_sub_callback(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_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; + + if (pin->Clearance == 0) + return PCB_R_DIR_NOT_FOUND; + i = pcb_layer_id(info->data, info->layer); + if (PCB_FLAG_THERM_TEST(i, pin)) { + np = pcb_thermal_area_pin(pcb_data_get_top(info->data), pin, i); + if (!np) + return PCB_R_DIR_FOUND_CONTINUE; + } + else { + np = pcb_poly_from_pin(pin, PIN_SIZE(pin), pin->Clearance); + 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_PIN_VIA_BATCH_SIZE) + subtract_accumulated(info, polygon); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +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; + + pcb_polyarea_boolean_free(info->accumulate, np, &merged, PCB_PBO_UNITE); + info->accumulate = merged; + + info->batch_size++; + + 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; + 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_TYPE_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; + + if (SubtractPolyPoly(subpoly, polygon) < 0) + longjmp(info->env, 1); + + return PCB_R_DIR_FOUND_CONTINUE; +} + +static pcb_r_dir_t pad_sub_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_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 (pad->Clearance == 0) + return PCB_R_DIR_NOT_FOUND; + polygon = info->polygon; + if (PCB_XOR(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad), !info->solder)) { + if (SubtractPad(pad, polygon) < 0) + longjmp(info->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; + } + return PCB_R_DIR_NOT_FOUND; +} + +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; + + 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; + polygon = info->polygon; + if (SubtractText(text, polygon) < 0) + longjmp(info->env, 1); + return PCB_R_DIR_FOUND_CONTINUE; +} + +static int clearPoly(pcb_data_t *Data, pcb_layer_t *Layer, pcb_poly_t * polygon, const pcb_box_t * here, pcb_coord_t expand) +{ + int r = 0, seen; + pcb_box_t region; + struct cpInfo info; + pcb_layergrp_id_t group; + unsigned int gflg; + pcb_layer_type_t lf; + + 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; + + 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; + if (info.solder || (gflg & PCB_LYT_TOP)) { + pcb_r_search(Data->pad_tree, ®ion, NULL, pad_sub_callback, &info, &seen); + r += seen; + } + 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->via_tree, ®ion, NULL, pin_sub_callback, &info, &seen); + r += seen; + pcb_r_search(Data->pin_tree, ®ion, NULL, pin_sub_callback, &info, &seen); + r += seen; + pcb_r_search(Data->padstack_tree, ®ion, NULL, padstack_sub_callback, &info, &seen); + r += seen; + subtract_accumulated(&info, polygon); + } + polygon->NoHolesValid = 0; + 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; + 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); + + 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 UnsubtractPin(pcb_pin_t * pin, 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(&pin->BoundingBox, UNSUBTRACT_BLOAT * 400000); + + if (!np) + return 0; + if (!Unsubtract(np, p)) + return 0; + + clearPoly(PCB->Data, l, p, (const pcb_box_t *) pin, 2 * UNSUBTRACT_BLOAT * 400000); + return 1; +} + +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); + 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); + 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); + 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); + return 1; +} + +static int UnsubtractPad(pcb_pad_t * pad, pcb_layer_t * l, pcb_poly_t * p) +{ + pcb_polyarea_t *np; + + /* overlap a bit to prevent notches from rounding errors */ + np = pcb_poly_from_box_bloated(&pad->BoundingBox, UNSUBTRACT_BLOAT); + + if (!np) + return 0; + if (!Unsubtract(np, p)) + return 0; + clearPoly(PCB->Data, l, p, (const pcb_box_t *) pad, 2 * UNSUBTRACT_BLOAT); + return 1; +} + +static pcb_bool inhibit = pcb_false; + +int pcb_poly_init_clip(pcb_data_t *Data, pcb_layer_t *layer, pcb_poly_t * p) +{ + pcb_board_t *pcb; + + if (inhibit) + return 0; + + if (layer->is_bound) + layer = layer->meta.bound.real; + + if (p->Clipped) + pcb_polyarea_free(&p->Clipped); + p->Clipped = original_poly(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; + + if (PCB_FLAG_TEST(PCB_FLAG_CLEARPOLY, p)) + clearPoly(Data, layer, p, NULL, 0); + else + p->NoHolesValid = 0; + return 1; +} + +/* -------------------------------------------------------------------------- + * 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_TYPE_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; + pcb_added_lines = 0; + 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_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; + pcb_added_lines = 0; + + /* add to undo list */ + pcb_undo_add_obj_to_create(PCB_TYPE_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_TYPE_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; + pcb_added_lines = 0; +} + +/* 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; + pcb_r_dir_t (*callback) (pcb_data_t *, pcb_layer_t *, pcb_poly_t *, int, void *, void *); +}; + +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) +{ + if (!Polygon->Clipped) + return 0; + switch (type) { + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + SubtractPin(Data, (pcb_pin_t *) ptr2, Layer, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_PSTK: + SubtractPadstack(Data, (pcb_pstk_t *) ptr2, Layer, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_LINE: + SubtractLine((pcb_line_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_ARC: + SubtractArc((pcb_arc_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_POLY: + if (ptr2 != Polygon) { + SubtractPolyPoly((pcb_poly_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + } + break; + case PCB_TYPE_PAD: + SubtractPad((pcb_pad_t *) ptr2, Polygon); + Polygon->NoHolesValid = 0; + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_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) +{ + switch (type) { + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + UnsubtractPin((pcb_pin_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_PSTK: + UnsubtractPadstack(Data, (pcb_pstk_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_LINE: + UnsubtractLine((pcb_line_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_ARC: + UnsubtractArc((pcb_arc_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_POLY: + if (ptr2 != Polygon) { + UnsubtractPolyPoly((pcb_poly_t *) ptr2, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + } + break; + case PCB_TYPE_PAD: + UnsubtractPad((pcb_pad_t *) ptr2, Layer, Polygon); + return PCB_R_DIR_FOUND_CONTINUE; + case PCB_TYPE_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) == 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) == 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); + return PCB_R_DIR_NOT_FOUND; +} + +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)) +{ + pcb_box_t sb = ((pcb_pin_t *) ptr2)->BoundingBox; + int r = 0, seen; + struct plow_info info; + + info.type = type; + info.ptr1 = ptr1; + info.ptr2 = ptr2; + info.data = Data; + info.callback = call_back; + switch (type) { + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + if (pcb_data_get_top(Data) == NULL) /* don't do it if not on a board */ + break; + if (type == PCB_TYPE_PIN || ptr1 == ptr2 || ptr1 == NULL) { + LAYER_LOOP(Data, pcb_max_layer); + { + if (!(pcb_layer_flags_(layer) & PCB_LYT_COPPER)) + continue; + info.layer = layer; + pcb_r_search(layer->polygon_tree, &sb, NULL, plow_callback, &info, &seen); + r += seen; + } + PCB_END_LOOP; + } + else { + 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; + case PCB_TYPE_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); + } + 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_TYPE_POLY: + if (!PCB_POLY_HAS_CLEARANCE((pcb_poly_t *) ptr2)) + return 0; + goto doit; + + case PCB_TYPE_LINE: + case PCB_TYPE_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_TYPE_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 */ +#warning 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; + case PCB_TYPE_PAD: + { + pcb_layergrp_id_t SLayer, CLayer, group; + + SLayer = CLayer = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &SLayer, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &CLayer, 1); + group = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (pcb_pad_t *) ptr2) ? SLayer : CLayer; + PCB_COPPER_GROUP_LOOP(Data, group); + { + info.layer = layer; + pcb_r_search(layer->polygon_tree, &sb, NULL, plow_callback, &info, &seen); + r += seen; + } + PCB_END_LOOP; + } + break; + + case PCB_TYPE_ELEMENT: + { + PCB_PIN_LOOP((pcb_element_t *) ptr1); + { + pcb_poly_plows(Data, PCB_TYPE_PIN, ptr1, pin, call_back); + } + PCB_END_LOOP; + PCB_PAD_LOOP((pcb_element_t *) ptr1); + { + pcb_poly_plows(Data, PCB_TYPE_PAD, ptr1, pad, call_back); + } + 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->parent_type == PCB_PARENT_SUBC) + dt = dt->parent.subc->parent.data; + if (dt->parent_type != PCB_PARENT_BOARD) /* clear/restore only on boards */ + return; + if (type == PCB_TYPE_POLY) + pcb_poly_init_clip(dt, (pcb_layer_t *) ptr1, (pcb_poly_t *) ptr2); + pcb_poly_plows(dt, type, ptr1, ptr2, add_plow); +} + +void pcb_poly_clear_from_poly(pcb_data_t * Data, int type, void *ptr1, void *ptr2) +{ + pcb_data_t *dt = Data; + while(dt->parent_type == PCB_PARENT_SUBC) + dt = dt->parent.subc->parent.data; + if (dt->parent_type != PCB_PARENT_BOARD) /* clear/restore only on boards */ + return; + if (type == PCB_TYPE_POLY) + pcb_poly_init_clip(dt, (pcb_layer_t *) ptr1, (pcb_poly_t *) ptr2); + pcb_poly_plows(dt, type, ptr1, ptr2, subtract_plow); +} + +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); +} + +/* 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 > PCB->IsleArea) { + 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_TYPE_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, 0); + 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(NULL, 0, 0); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + + pcb_poly_invalidate_draw(Layer, Polygon); + /* add to undo list */ + pcb_undo_add_obj_to_create(PCB_TYPE_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/1.2.7/src/polygon.h =================================================================== --- tags/1.2.7/src/polygon.h (nonexistent) +++ tags/1.2.7/src/polygon.h (revision 13657) @@ -0,0 +1,117 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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); +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 *, int, void *, void *, + pcb_r_dir_t (*callback) (pcb_data_t *, pcb_layer_t *, pcb_poly_t *, int, void *, void *)); +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_pin(pcb_pin_t * l, pcb_coord_t thick, pcb_coord_t clear); +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 *); + +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_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/1.2.7/src/polygon1.c =================================================================== --- tags/1.2.7/src/polygon1.c (nonexistent) +++ tags/1.2.7/src/polygon1.c (revision 13657) @@ -0,0 +1,3439 @@ +/* + 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 +static void DEBUGP(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + pcb_vfprintf(stderr, fmt, ap); + va_end(ap); +} +#else +static 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, 1); + 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, 1); + pcb_r_delete_entry(tree, (const pcb_box_t *) 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(NULL, 0, 0); + 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, 1); + } + 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(NULL, 0, 0); + pcb_r_insert_entry(newp->contour_tree, (pcb_box_t *) c, 0); + 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, 0); + } + } + 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(NULL, 0, 0); + 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], 0); + 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, 0); + + } + } + 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_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(NULL, 0, 0); + + 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, 0); + 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, 0); + 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(NULL, 0, 0); +} + +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 */ +pcb_bool pcb_polyarea_contour_check(pcb_pline_t * a) +{ + pcb_vnode_t *a1, *a2, *hit1, *hit2; + pcb_vector_t i1, i2; + int icnt; + + 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) + return pcb_true; + + if (pcb_vect_dist2(i1, a1->point) < EPSILON) + hit1 = a1; + else if (pcb_vect_dist2(i1, a1->next->point) < EPSILON) + hit1 = a1->next; + else + hit1 = NULL; + + if (pcb_vect_dist2(i1, a2->point) < EPSILON) + hit2 = a2; + else if (pcb_vect_dist2(i1, a2->next->point) < 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. + */ + return pcb_true; + } + 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)) + return pcb_true; + } + 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)) + return pcb_true; + } + 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)) + return pcb_true; + } + } + } + while ((a2 = a2->next) != &a->head); + } + while ((a1 = a1->next) != &a->head); + return pcb_false; +} + +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) +{ + 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 (c->Flags.orient == PCB_PLF_INV) + DEBUGP("failed orient\n"); + if (pcb_polyarea_contour_check(c)) + DEBUGP("failed self-intersection\n"); + + + 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, "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); + pcb_fprintf(stderr, "flush\n"); + pcb_fprintf(stderr, "!!!animator end\n"); +#undef update_minmax +} +#endif + + +pcb_bool pcb_poly_valid(pcb_polyarea_t * p) +{ + pcb_pline_t *c; + + if ((p == NULL) || (p->contours == NULL)) + return pcb_false; + + if (p->contours->Flags.orient == PCB_PLF_INV || pcb_polyarea_contour_check(p->contours)) { +#ifndef NDEBUG + DEBUGP("Invalid Outer pcb_pline_t\n"); + pcb_poly_valid_report(p->contours, &p->contours->head); +#endif + return pcb_false; + } + for (c = p->contours->next; c != NULL; c = c->next) { + if (c->Flags.orient == PCB_PLF_DIR || pcb_polyarea_contour_check(c) || !pcb_poly_contour_in_contour(p->contours, c)) { +#ifndef NDEBUG + DEBUGP("Invalid Inner pcb_pline_t orient = %d\n", c->Flags.orient); + pcb_poly_valid_report(c, &c->head); +#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 Tibor 'Igor2' Palinkas +*/ + +typedef struct { + pcb_vector_t l1, l2; +} 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)) + 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) +{ + 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); + + return pcb_r_search(pl->tree, &lbx, NULL, pline_isect_line_cb, &ctx, NULL) == PCB_R_DIR_CANCEL; +} + +/* + * 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 = 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; + + 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(NULL, 0, 0); + 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_destroy_tree(&pl->tree); + pl->tree = (pcb_rtree_t *)make_edge_tree(pl); + + pcb_r_insert_entry(pa->contour_tree, (pcb_box_t *)pl, 0); + } + } +} + + +/* 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/1.2.7/src/polygon_act.c =================================================================== --- tags/1.2.7/src/polygon_act.c (nonexistent) +++ tags/1.2.7/src/polygon_act.c (revision 13657) @@ -0,0 +1,157 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "undo.h" +#include "funchash_core.h" + +#include "polygon.h" +#include "draw.h" +#include "search.h" +#include "crosshair.h" +#include "compat_nls.h" + +#include "obj_poly.h" + +/* --------------------------------------------------------------------------- */ + +static const char morphpcb_polygon_syntax[] = "pcb_poly_morph(Object|Selected)"; + +static const char pcb_acth_MorphPolygon[] = "Converts dead polygon islands into separate polygons."; + +/* %start-doc actions MorphPolygon + +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. + +%end-doc */ + +static int pcb_act_MorphPolygon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + { + int type; + void *ptr1, *ptr2, *ptr3; + + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_TYPE_POLY, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + 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; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_polygon_syntax[] = "Polygon(Close|CloseHole|PreviousPoint)"; + +static const char pcb_acth_Polygon[] = "Some polygon related stuff."; + +/* %start-doc actions Polygon + +Polygons need a special action routine to make life easier. + +@table @code + +@item 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. + +@item 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. + +@item PreviousPoint +Resets the newly entered corner to the previous one. The Undo action +will call Polygon(PreviousPoint) when appropriate to do so. + +@end table + +%end-doc */ + +static int pcb_act_Polygon(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function && ((conf_core.editor.mode == PCB_MODE_POLYGON) || (conf_core.editor.mode == PCB_MODE_POLYGON_HOLE))) { + pcb_notify_crosshair_change(pcb_false); + switch (pcb_funchash_get(function, NULL)) { + /* 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); + } + return 0; +} + + +pcb_hid_action_t polygon_action_list[] = { + {"MorphPolygon", 0, pcb_act_MorphPolygon, + pcb_acth_MorphPolygon, morphpcb_polygon_syntax} + , + {"Polygon", 0, pcb_act_Polygon, + pcb_acth_Polygon, pcb_polygon_syntax} +}; + +PCB_REGISTER_ACTIONS(polygon_action_list, NULL) Index: tags/1.2.7/src/polygon_offs.c =================================================================== --- tags/1.2.7/src/polygon_offs.c (nonexistent) +++ tags/1.2.7/src/polygon_offs.c (revision 13657) @@ -0,0 +1,116 @@ +/* + * 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. + * + */ + +/* Polygon contour offset calculation */ + +static void 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; +} + +static void ll_intersect(double *xi, double *yi, double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2) +{ + double ua, X1, Y1, X2, Y2, X3, Y3, X4, Y4, tmp; + + /* 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 */ + *xi = ax2; + *yi = 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); +} + + +pcb_pline_t *pcb_pline_dup_offset(const pcb_pline_t *src, pcb_coord_t offs) +{ + const pcb_vnode_t *p = NULL, *v, *n; + pcb_vector_t tmp; + pcb_pline_t *res = NULL; + double nx, ny, px, py; + int num_pts, i; + + v = &src->head; + num_pts = 0; + do { + num_pts++; + } while((v = v->next) != &src->head); + + + v = &src->head; + i = 0; + do { + n = v->next; + norm(&nx, &ny, v->point[0], v->point[1], n->point[0], n->point[1]); + + if (p != NULL) { + double xi, yi, vx1, vy1, vx2, vy2, nx1, ny1, nx2, ny2; + + vx1 = p->point[0] - px*offs; + vy1 = p->point[1] - py*offs; + vx2 = v->point[0] - px*offs; + vy2 = v->point[1] - py*offs; + + nx1 = v->point[0] - nx*offs; + ny1 = v->point[1] - ny*offs; + nx2 = n->point[0] - nx*offs; + ny2 = n->point[1] - ny*offs; + + ll_intersect(&xi, &yi, vx1, vy1, vx2, vy2, nx1, ny1, nx2, ny2); + + tmp[0] = xi; + tmp[1] = yi; + if (res == NULL) + res = pcb_poly_contour_new(tmp); + else + pcb_poly_vertex_include(res->head.prev, pcb_poly_node_create(tmp)); + } + + p = v; + v = v->next; + px = nx; + py = ny; + i++; + } + while(i <= num_pts); + + return res; +} Index: tags/1.2.7/src/polygon_offs.h =================================================================== --- tags/1.2.7/src/polygon_offs.h (nonexistent) +++ tags/1.2.7/src/polygon_offs.h (revision 13657) @@ -0,0 +1,26 @@ +/* + * 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. + * + */ + +/* Polygon contour offset calculation */ + +pcb_pline_t *pcb_pline_dup_offset(const pcb_pline_t *src, pcb_coord_t offs); + Index: tags/1.2.7/src/rats.c =================================================================== --- tags/1.2.7/src/rats.c (nonexistent) +++ tags/1.2.7/src/rats.c (revision 13657) @@ -0,0 +1,1096 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * This module, rats.c, was written and is Copyright (C) 1997 by harry eaton + * 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. + * + */ + +/* rats nest routines */ + +#include "config.h" +#include "conf_core.h" + +#include +#include + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.h" +#include "find.h" +#include "polygon.h" +#include "rats.h" +#include "search.h" +#include "undo.h" +#include "stub_mincut.h" +#include "route_style.h" +#include "compat_misc.h" +#include "netlist.h" +#include "compat_nls.h" +#include +#include "obj_rat_draw.h" +#include "obj_term.h" +#include "obj_subc_parent.h" + +#define STEP_POINT 100 + +#define TRIEDFIRST 0x1 +#define BESTFOUND 0x2 + +/* --------------------------------------------------------------------------- + * some forward declarations + */ +static pcb_bool pcb_term_find_name_ppt(const char *, const char *, pcb_connection_t *, pcb_bool); +static pcb_bool ParseConnection(const char *, char *, char *); +static pcb_bool DrawShortestRats(pcb_netlist_t *, + void (*)(register pcb_connection_t *, register pcb_connection_t *, register pcb_route_style_t *)); +static pcb_bool GatherSubnets(pcb_netlist_t *, pcb_bool, pcb_bool); +static pcb_bool CheckShorts(pcb_lib_menu_t *); +static void TransferNet(pcb_netlist_t *, pcb_net_t *, pcb_net_t *); + +static pcb_bool badnet = pcb_false; +static pcb_layergrp_id_t Sgrp = -1, Cgrp = -1; /* layer group holding solder/component side */ + +/* --------------------------------------------------------------------------- + * parse a connection description from a string + * puts the element name in the string and the pin number in + * the number. If a valid connection is found, it returns the + * number of characters processed from the string, otherwise + * it returns 0 + */ +static pcb_bool ParseConnection(const char *InString, char *ElementName, char *PinNum) +{ + int i, j; + + /* copy element name portion */ + for (j = 0; InString[j] != '\0' && InString[j] != '-'; j++) + ElementName[j] = InString[j]; + if (InString[j] == '-') { + for (i = j; i > 0 && ElementName[i - 1] >= 'a'; i--); + ElementName[i] = '\0'; + for (i = 0, j++; InString[j] != '\0'; i++, j++) + PinNum[i] = InString[j]; + PinNum[i] = '\0'; + return (pcb_false); + } + else { + ElementName[j] = '\0'; + pcb_message(PCB_MSG_ERROR, _("Bad net-list format encountered near: \"%s\"\n"), ElementName); + return (pcb_true); + } +} + +/* --------------------------------------------------------------------------- + * Find a particular terminal from an element/subc name and pin/pad/terminal number + */ +#warning term TODO: once pins and pads are gone, move this to obj_term.c +static pcb_bool pcb_term_find_name_ppt(const char *ElementName, const char *PinNum, pcb_connection_t * conn, pcb_bool Same) +{ + pcb_element_t *element; + gdl_iterator_t it; + pcb_pad_t *pad; + pcb_pin_t *pin; + pcb_any_obj_t *obj; + + /* first check for subcircuits; this is the only one thing we'll need to do + once elements are removed */ + obj = pcb_term_find_name(PCB, PCB->Data, PCB_LYT_COPPER, ElementName, PinNum, Same, (pcb_subc_t **)&conn->ptr1, &conn->group); + if (obj != NULL) { + conn->obj = obj; + pcb_obj_center(obj, &conn->X, &conn->Y); + return pcb_true; + } + + if ((element = pcb_search_elem_by_name(PCB->Data, ElementName)) == NULL) + return pcb_false; + + padlist_foreach(&element->Pad, &it, pad) { + if (PCB_NSTRCMP(PinNum, pad->Number) == 0 && (!Same || !PCB_FLAG_TEST(PCB_FLAG_DRC, pad))) { + conn->ptr1 = element; + conn->obj = (pcb_any_obj_t *)pad; + conn->group = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? Sgrp : Cgrp; + + if (PCB_FLAG_TEST(PCB_FLAG_EDGE2, pad)) { + conn->X = pad->Point2.X; + conn->Y = pad->Point2.Y; + } + else { + conn->X = pad->Point1.X; + conn->Y = pad->Point1.Y; + } + return pcb_true; + } + } + + padlist_foreach(&element->Pin, &it, pin) { + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pin) && pin->Number && PCB_NSTRCMP(PinNum, pin->Number) == 0 && (!Same || !PCB_FLAG_TEST(PCB_FLAG_DRC, pin))) { + conn->ptr1 = element; + conn->obj = (pcb_any_obj_t *)pin; + conn->group = Sgrp; /* any layer will do */ + conn->X = pin->X; + conn->Y = pin->Y; + return pcb_true; + } + } + + return pcb_false; +} + +pcb_bool pcb_rat_seek_pad(pcb_lib_entry_t * entry, pcb_connection_t * conn, pcb_bool Same) +{ + int j; + char ElementName[256]; + char PinNum[256]; + + if (ParseConnection(entry->ListEntry, ElementName, PinNum)) + return (pcb_false); + for (j = 0; PinNum[j] != '\0'; j++); + if (j == 0) { + pcb_message(PCB_MSG_ERROR, _("Error! Netlist file is missing pin!\n" "white space after \"%s-\"\n"), ElementName); + badnet = pcb_true; + } + else { + if (pcb_term_find_name_ppt(ElementName, PinNum, conn, Same)) + return (pcb_true); + if (Same) + return (pcb_false); + if (PinNum[j - 1] < '0' || PinNum[j - 1] > '9') { + pcb_message(PCB_MSG_WARNING, "WARNING! Pin number ending with '%c'" + " encountered in netlist file\n" "Probably a bad netlist file format\n", PinNum[j - 1]); + } + } + pcb_message(PCB_MSG_WARNING, _("Can't find %s pin %s called for in netlist.\n"), ElementName, PinNum); + return (pcb_false); +} + +static const char *get_refdes(void *ptr1) +{ + pcb_any_obj_t *obj = ptr1; + switch(obj->type) { + case PCB_OBJ_ELEMENT: return PCB_ELEM_NAME_REFDES((pcb_element_t *)ptr1); + case PCB_OBJ_SUBC: + if (((pcb_subc_t *)ptr1)->refdes != NULL) + return ((pcb_subc_t *)ptr1)->refdes; + return ""; + default: + break; + } + return ""; +} + +static const char *get_termid(pcb_any_obj_t *obj) +{ + switch(obj->type) { + case PCB_OBJ_PIN: return ((pcb_pin_t *)obj)->Number; + case PCB_OBJ_PAD: return ((pcb_pad_t *)obj)->Number; + default: return obj->term; + } +} + +static void clear_drc_flag(int clear_ratconn) +{ + pcb_rtree_it_t it; + pcb_box_t *n; + int li; + pcb_layer_t *l; + + for(n = pcb_r_first(PCB->Data->pin_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (clear_ratconn) + ((pcb_pin_t *)n)->ratconn = NULL; + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_pin_t *)n); + } + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->via_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_pin_t *)n); + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->padstack_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_pstk_t *)n); + pcb_r_end(&it); + + for(n = pcb_r_first(PCB->Data->pad_tree, &it); n != NULL; n = pcb_r_next(&it)) { + if (clear_ratconn) + ((pcb_pad_t *)n)->ratconn = NULL; + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_pad_t *)n); + } + pcb_r_end(&it); + + for(li = 0, l = PCB->Data->Layer; li < PCB->Data->LayerN; li++,l++) { + for(n = pcb_r_first(l->line_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_line_t *)n); + pcb_r_end(&it); + + for(n = pcb_r_first(l->arc_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_arc_t *)n); + pcb_r_end(&it); + + for(n = pcb_r_first(l->polygon_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_poly_t *)n); + pcb_r_end(&it); + + for(n = pcb_r_first(l->text_tree, &it); n != NULL; n = pcb_r_next(&it)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, (pcb_text_t *)n); + pcb_r_end(&it); + } +} + +pcb_netlist_t *pcb_rat_proc_netlist(pcb_lib_t *net_menu) +{ + pcb_connection_t *connection; + pcb_connection_t LastPoint; + pcb_net_t *net; + static pcb_netlist_t *Wantlist = NULL; + + if (!net_menu->MenuN) + return (NULL); + pcb_netlist_free(Wantlist); + free(Wantlist); + badnet = pcb_false; + + /* find layer groups of the component side and solder side */ + Sgrp = Cgrp = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &Sgrp, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &Cgrp, 1); + + Wantlist = (pcb_netlist_t *) calloc(1, sizeof(pcb_netlist_t)); + if (Wantlist) { + clear_drc_flag(1); + PCB_MENU_LOOP(net_menu); + { + if (menu->Name[0] == '*' || menu->flag == 0) { + badnet = pcb_true; + continue; + } + net = pcb_net_new(Wantlist); + if (menu->Style) { + int idx = pcb_route_style_lookup(&PCB->RouteStyle, -1, -1, -1, -1, menu->Style); + if (idx >= 0) + net->Style = PCB->RouteStyle.array+idx; + } + else /* default to NULL if none found */ + net->Style = NULL; + PCB_ENTRY_LOOP(menu); + { + if (pcb_rat_seek_pad(entry, &LastPoint, pcb_false)) { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, (pcb_pin_t *) LastPoint.obj)) + pcb_message(PCB_MSG_ERROR, _ + ("Error! Element %s pin %s appears multiple times in the netlist file.\n"), + get_refdes(LastPoint.ptr1), get_termid(LastPoint.obj)); + else { + connection = pcb_rat_connection_alloc(net); + *connection = LastPoint; + /* indicate expect net */ + connection->menu = menu; + /* mark as visited */ + PCB_FLAG_SET(PCB_FLAG_DRC, (pcb_pin_t *) LastPoint.obj); + LastPoint.obj->ratconn = (void *)menu; + } + } + else + badnet = pcb_true; + /* check for more pins with the same number */ + for (; pcb_rat_seek_pad(entry, &LastPoint, pcb_true);) { + connection = pcb_rat_connection_alloc(net); + *connection = LastPoint; + /* indicate expect net */ + connection->menu = menu; + /* mark as visited */ + PCB_FLAG_SET(PCB_FLAG_DRC, (pcb_pin_t *) LastPoint.obj); + LastPoint.obj->ratconn = (void *)menu; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + + /* clear all visit marks */ + clear_drc_flag(0); + + return (Wantlist); +} + +/* + * copy all connections from one net into another + * and then remove the first net from its netlist + */ +static void TransferNet(pcb_netlist_t *Netl, pcb_net_t *SourceNet, pcb_net_t *DestNet) +{ + pcb_connection_t *conn; + + /* It would be worth checking if SourceNet is NULL here to avoid a segfault. Seb James. */ + PCB_CONNECTION_LOOP(SourceNet); + { + conn = pcb_rat_connection_alloc(DestNet); + *conn = *connection; + } + PCB_END_LOOP; + DestNet->Style = SourceNet->Style; + /* free the connection memory */ + pcb_net_free(SourceNet); + /* remove SourceNet from its netlist */ + *SourceNet = Netl->Net[--(Netl->NetN)]; + /* zero out old garbage */ + memset(&Netl->Net[Netl->NetN], 0, sizeof(pcb_net_t)); +} + +static void **found_short(pcb_any_obj_t *parent, pcb_any_obj_t *term, vtp0_t *generic, pcb_lib_menu_t *theNet, void **menu) +{ + pcb_bool newone; + int i; + + if (!term->ratconn) { + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to %s terminal %s\n"), + &theNet->Name[2], PCB_UNKNOWN(get_refdes(parent)), PCB_UNKNOWN(get_termid(term))); + pcb_stub_rat_found_short(term, &theNet->Name[2]); + return menu; + } + + newone = pcb_true; + for(i = 0; i < vtp0_len(generic); i++) { + if (generic->array[i] == term->ratconn) { + newone = pcb_false; + break; + } + } + + if (newone) { + menu = vtp0_alloc_append(generic, 1); + *menu = term->ratconn; + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to net \"%s\"\n"), + &theNet->Name[2], &((pcb_lib_menu_t *) (term->ratconn))->Name[2]); + pcb_stub_rat_found_short((pcb_any_obj_t *)term, &theNet->Name[2]); + } + return menu; +} + +static void **find_shorts_in_subc(pcb_subc_t *subc_in, vtp0_t *generic, pcb_lib_menu_t *theNet, void **menu, pcb_bool *warn) +{ + if (PCB_FLAG_TEST(PCB_FLAG_NONETLIST, subc_in)) + return menu; + + PCB_VIA_LOOP(subc_in->data); + { + if (via->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, via)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)via, generic, theNet, menu); + } + } + PCB_END_LOOP; + + PCB_PADSTACK_LOOP(subc_in->data); + { + if (padstack->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, padstack)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)padstack, generic, theNet, menu); + } + } + PCB_END_LOOP; + + PCB_LINE_ALL_LOOP(subc_in->data); + { + if (line->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, line)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)line, generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + + PCB_ARC_ALL_LOOP(subc_in->data); + { + if (arc->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, arc)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)arc, generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + + PCB_POLY_ALL_LOOP(subc_in->data); + { + if (polygon->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, polygon)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)polygon, generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + + PCB_TEXT_ALL_LOOP(subc_in->data); + { + if (text->term == NULL) + continue; + if (PCB_FLAG_TEST(PCB_FLAG_DRC, text)) { + *warn = pcb_true; + menu = found_short((pcb_any_obj_t *)subc_in, (pcb_any_obj_t *)text, generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + + PCB_SUBC_LOOP(subc_in->data); + { + menu = find_shorts_in_subc(subc, generic, theNet, menu, warn); + } + PCB_END_LOOP; + return menu; +} + + +static pcb_bool CheckShorts(pcb_lib_menu_t *theNet) +{ + pcb_bool warn = pcb_false; + vtp0_t generic; + /* the first connection was starting point so + * the menu is always non-null + */ + void **menu; + + vtp0_init(&generic); + menu = vtp0_alloc_append(&generic, 1); + *menu = theNet; + PCB_PIN_ALL_LOOP(PCB->Data); + { + pcb_element_t *e = pin->Element; +/* TODO: should be: !PCB_FLAG_TEST(PCB_FLAG_NONETLIST, (pcb_element_t *)pin->Element)*/ + if ((PCB_FLAG_TEST(PCB_FLAG_DRC, pin)) && (!(e->Flags.f & PCB_FLAG_NONETLIST)) && (!(e->Name->Flags.f & PCB_FLAG_NONETLIST))) { + warn = pcb_true; + menu = found_short((pcb_any_obj_t *)element, (pcb_any_obj_t *)pin, &generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + PCB_PAD_ALL_LOOP(PCB->Data); + { + pcb_element_t *e = pad->Element; +/* TODO: should be: !PCB_FLAG_TEST(PCB_FLAG_NONETLIST, (pcb_element_t *)pad->Element)*/ + if ((PCB_FLAG_TEST(PCB_FLAG_DRC, pad)) && (!(e->Flags.f & PCB_FLAG_NONETLIST)) && (!(e->Name->Flags.f & PCB_FLAG_NONETLIST))) { + warn = pcb_true; + menu = found_short((pcb_any_obj_t *)element, (pcb_any_obj_t *)pad, &generic, theNet, menu); + } + } + PCB_ENDALL_LOOP; + PCB_SUBC_LOOP(PCB->Data); + { + menu = find_shorts_in_subc(subc, &generic, theNet, menu, &warn); + } + PCB_END_LOOP; + vtp0_uninit(&generic); + return (warn); +} + +static void gather_subnet_objs(pcb_data_t *data, pcb_netlist_t *Netl, pcb_net_t *a) +{ + pcb_connection_t *conn; + + /* now add other possible attachment points to the subnet */ + /* e.g. line end-points and vias */ + /* don't add non-manhattan lines, the auto-router can't route to them */ + PCB_LINE_COPPER_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, line) + && ((line->Point1.X == line->Point2.X) + || (line->Point1.Y == line->Point2.Y))) { + conn = pcb_rat_connection_alloc(a); + conn->X = line->Point1.X; + conn->Y = line->Point1.Y; + conn->ptr1 = layer; + conn->obj = (pcb_any_obj_t *)line; + conn->group = pcb_layer_get_group_(layer); + conn->menu = NULL; /* agnostic view of where it belongs */ + conn = pcb_rat_connection_alloc(a); + conn->X = line->Point2.X; + conn->Y = line->Point2.Y; + conn->ptr1 = layer; + conn->obj = (pcb_any_obj_t *)line; + conn->group = pcb_layer_get_group_(layer); + conn->menu = NULL; + if PCB_FLAG_TEST(PCB_FLAG_DRC_INTCONN, line) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, line); + } + } + PCB_ENDALL_LOOP; +#warning term TODO: and what about arcs and text? + /* add polygons so the auto-router can see them as targets */ + PCB_POLY_COPPER_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, polygon)) { + conn = pcb_rat_connection_alloc(a); + /* make point on a vertex */ + conn->X = polygon->Clipped->contours->head.point[0]; + conn->Y = polygon->Clipped->contours->head.point[1]; + conn->ptr1 = layer; + conn->obj = (pcb_any_obj_t *)polygon; + conn->group = pcb_layer_get_group_(layer); + conn->menu = NULL; /* agnostic view of where it belongs */ + if PCB_FLAG_TEST(PCB_FLAG_DRC_INTCONN, polygon) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, polygon); + } + } + PCB_ENDALL_LOOP; + PCB_VIA_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, via)) { + conn = pcb_rat_connection_alloc(a); + conn->X = via->X; + conn->Y = via->Y; + conn->ptr1 = via; + conn->obj = (pcb_any_obj_t *)via; + conn->group = Sgrp; + if PCB_FLAG_TEST(PCB_FLAG_DRC_INTCONN, via) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, via); + } + } + PCB_END_LOOP; + PCB_PADSTACK_LOOP(data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, padstack)) { + conn = pcb_rat_connection_alloc(a); + conn->X = padstack->x; + conn->Y = padstack->y; + conn->ptr1 = padstack; + conn->obj = (pcb_any_obj_t *)padstack; + conn->group = Sgrp; + if PCB_FLAG_TEST(PCB_FLAG_DRC_INTCONN, padstack) + PCB_FLAG_CLEAR(PCB_FLAG_DRC | PCB_FLAG_DRC_INTCONN, padstack); + } + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(data); + { + gather_subnet_objs(subc->data, Netl, a); + } + PCB_END_LOOP; +} + +/* --------------------------------------------------------------------------- + * Determine existing interconnections of the net and gather into sub-nets + * + * initially the netlist has each connection in its own individual net + * afterwards there can be many fewer nets with multiple connections each + */ +static pcb_bool GatherSubnets(pcb_netlist_t *Netl, pcb_bool NoWarn, pcb_bool AndRats) +{ + pcb_net_t *a, *b; + pcb_bool Warned = pcb_false; + pcb_cardinal_t m, n; + + for (m = 0; Netl->NetN > 0 && m < Netl->NetN; m++) { + a = &Netl->Net[m]; + pcb_reset_conns(pcb_false); + pcb_rat_find_hook(a->Connection[0].obj, pcb_false, AndRats); + + /* now anybody connected to the first point has PCB_FLAG_DRC set */ + /* so move those to this subnet */ + PCB_FLAG_CLEAR(PCB_FLAG_DRC, (pcb_pin_t *) a->Connection[0].obj); + for (n = m + 1; n < Netl->NetN; n++) { + b = &Netl->Net[n]; + /* There can be only one connection in net b */ + if (PCB_FLAG_TEST(PCB_FLAG_DRC, (pcb_pin_t *) b->Connection[0].obj)) { + PCB_FLAG_CLEAR(PCB_FLAG_DRC, (pcb_pin_t *) b->Connection[0].obj); + TransferNet(Netl, b, a); + /* back up since new subnet is now at old index */ + n--; + } + } + + gather_subnet_objs(PCB->Data, Netl, a); + if (!NoWarn) + Warned |= CheckShorts(a->Connection[0].menu); + } + pcb_reset_conns(pcb_false); + return (Warned); +} + +/* --------------------------------------------------------------------------- + * Draw a rat net (tree) having the shortest lines + * this also frees the subnet memory as they are consumed + * + * Note that the Netl we are passed is NOT the main netlist - it's the + * connectivity for ONE net. It represents the CURRENT connectivity + * state for the net, with each Netl->Net[N] representing one + * copper-connected subset of the net. + */ + +static pcb_bool +DrawShortestRats(pcb_netlist_t *Netl, + void (*funcp) (register pcb_connection_t *, register pcb_connection_t *, register pcb_route_style_t *)) +{ + pcb_rat_t *line; + register float distance, temp; + register pcb_connection_t *conn1, *conn2, *firstpoint, *secondpoint; + pcb_poly_t *polygon; + pcb_bool changed = pcb_false; + pcb_bool havepoints; + pcb_cardinal_t n, m, j; + pcb_net_t *next, *subnet, *theSubnet = NULL; + + /* This is just a sanity check, to make sure we're passed + * *something*. + */ + if (!Netl || Netl->NetN < 1) + return pcb_false; + + /* + * Everything inside the NetList Netl should be connected together. + * Each Net in Netl is a group of Connections which are already + * connected together somehow, either by real wires or by rats we've + * already drawn. Each Connection is a vertex within that blob of + * connected items. This loop finds the closest vertex pairs between + * each blob and draws rats that merge the blobs until there's just + * one big blob. + * + * Just to clarify, with some examples: + * + * Each Netl is one full net from a netlist, like from gnetlist. + * Each Netl->Net[N] is a subset of that net that's already + * physically connected on the pcb. + * + * So a new design with no traces yet, would have a huge list of Net[N], + * each with one pin in it. + * + * A fully routed design would have one Net[N] with all the pins + * (for that net) in it. + */ + + /* + * We keep doing this do/while loop until everything's connected. + * I.e. once per rat we add. + */ + distance = 0.0; + havepoints = pcb_true; /* so we run the loop at least once */ + while (Netl->NetN > 1 && havepoints) { + /* This is the top of the "find one rat" logic. */ + havepoints = pcb_false; + firstpoint = secondpoint = NULL; + + /* Test Net[0] vs Net[N] for N=1..max. Find the shortest + distance between any two points in different blobs. */ + subnet = &Netl->Net[0]; + for (j = 1; j < Netl->NetN; j++) { + /* + * Scan between Net[0] blob (subnet) and Net[N] blob (next). + * Note the shortest distance we find. + */ + next = &Netl->Net[j]; + for (n = subnet->ConnectionN - 1; n != -1; n--) { + conn1 = &subnet->Connection[n]; + for (m = next->ConnectionN - 1; m != -1; m--) { + conn2 = &next->Connection[m]; + /* + * At this point, conn1 and conn2 are two pins in + * different blobs of the same net. See how far + * apart they are, and if they're "closer" than what + * we already have. + */ + + /* + * Prefer to connect Connections over polygons to the + * polygons (ie assume the user wants a via to a plane, + * not a daisy chain). Further prefer to pick an existing + * via in the Net to make that connection. + */ + if (conn1->obj->type == PCB_OBJ_POLY && + (polygon = (pcb_poly_t *) conn1->obj) && + !(distance == 0 && + firstpoint && firstpoint->obj->type == PCB_OBJ_VIA) && pcb_poly_is_point_in_p_ignore_holes(conn2->X, conn2->Y, polygon)) { + distance = 0; + firstpoint = conn2; + secondpoint = conn1; + theSubnet = next; + havepoints = pcb_true; + } + else if (conn2->obj->type == PCB_OBJ_POLY && + (polygon = (pcb_poly_t *) conn2->obj) && + !(distance == 0 && + firstpoint && firstpoint->obj->type == PCB_OBJ_VIA) && pcb_poly_is_point_in_p_ignore_holes(conn1->X, conn1->Y, polygon)) { + distance = 0; + firstpoint = conn1; + secondpoint = conn2; + theSubnet = next; + havepoints = pcb_true; + } + else if ((temp = PCB_SQUARE(conn1->X - conn2->X) + PCB_SQUARE(conn1->Y - conn2->Y)) < distance || !firstpoint) { + distance = temp; + firstpoint = conn1; + secondpoint = conn2; + theSubnet = next; + havepoints = pcb_true; + } + } + } + } + + /* + * If HAVEPOINTS is pcb_true, we've found a pair of points in two + * separate blobs of the net, and need to connect them together. + */ + if (havepoints) { + if (funcp) { + (*funcp) (firstpoint, secondpoint, subnet->Style); + } + else { + /* found the shortest distance subnet, draw the rat */ + if ((line = pcb_rat_new(PCB->Data, + firstpoint->X, firstpoint->Y, + secondpoint->X, secondpoint->Y, + firstpoint->group, secondpoint->group, conf_core.appearance.rat_thickness, pcb_no_flags())) != NULL) { + if (distance == 0) + PCB_FLAG_SET(PCB_FLAG_VIA, line); + pcb_undo_add_obj_to_create(PCB_TYPE_RATLINE, line, line, line); + pcb_rat_invalidate_draw(line); + changed = pcb_true; + } + } + + /* copy theSubnet into the current subnet */ + TransferNet(Netl, theSubnet, subnet); + } + } + + /* presently nothing to do with the new subnet */ + /* so we throw it away and free the space */ + pcb_net_free(&Netl->Net[--(Netl->NetN)]); + /* Sadly adding a rat line messes up the sorted arrays in connection finder */ + /* hace: perhaps not necessarily now that they aren't stored in normal layers */ + if (changed) { + pcb_conn_lookup_uninit(); + pcb_conn_lookup_init(); + } + return (changed); +} + +pcb_bool +pcb_rat_add_all(pcb_bool SelectedOnly, + void (*funcp) (register pcb_connection_t *, register pcb_connection_t *, register pcb_route_style_t *)) +{ + pcb_netlist_t *Nets, *Wantlist; + pcb_net_t *lonesome; + pcb_connection_t *onepin; + pcb_bool changed, Warned = pcb_false; + + /* the netlist library has the text form + * ProcNetlist fills in the Netlist + * structure the way the final routing + * is supposed to look + */ + Wantlist = pcb_rat_proc_netlist(&(PCB->NetlistLib[PCB_NETLIST_EDITED])); + if (!Wantlist) { + pcb_message(PCB_MSG_WARNING, _("Can't add rat lines because no netlist is loaded.\n")); + return (pcb_false); + } + changed = pcb_false; + /* initialize finding engine */ + pcb_conn_lookup_init(); + pcb_save_find_flag(PCB_FLAG_DRC); + Nets = (pcb_netlist_t *) calloc(1, sizeof(pcb_netlist_t)); + /* now we build another netlist (Nets) for each + * net in Wantlist that shows how it actually looks now, + * then fill in any missing connections with rat lines. + * + * we first assume each connection is separate + * (no routing), then gather them into groups + * if the net is all routed, the new netlist (Nets) + * will have only one net entry. + * Note that DrawShortestRats consumes all nets + * from Nets, so *Nets is empty after the + * DrawShortestRats call + */ + PCB_NET_LOOP(Wantlist); + { + PCB_CONNECTION_LOOP(net); + { + if (!SelectedOnly || PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_pin_t *) connection->obj)) { + lonesome = pcb_net_new(Nets); + onepin = pcb_rat_connection_alloc(lonesome); + *onepin = *connection; + lonesome->Style = net->Style; + } + } + PCB_END_LOOP; + Warned |= GatherSubnets(Nets, SelectedOnly, pcb_true); + if (Nets->NetN > 0) + changed |= DrawShortestRats(Nets, funcp); + } + PCB_END_LOOP; + pcb_netlist_free(Nets); + free(Nets); + pcb_conn_lookup_uninit(); + pcb_restore_find_flag(); + if (funcp) + return (pcb_true); + + if (Warned || changed) { + pcb_stub_rat_proc_shorts(); + pcb_draw(); + } + + if (Warned) + conf_core.temp.rat_warn = pcb_true; + + if (changed) { + pcb_undo_inc_serial(); + if (ratlist_length(&PCB->Data->Rat) > 0) { + pcb_message(PCB_MSG_INFO, "%d rat line%s remaining\n", ratlist_length(&PCB->Data->Rat), ratlist_length(&PCB->Data->Rat) > 1 ? "s" : ""); + } + return (pcb_true); + } + if (!SelectedOnly && !Warned) { + if (!ratlist_length(&PCB->Data->Rat) && !badnet) + pcb_message(PCB_MSG_INFO, _("Congratulations!!\n" "The layout is complete and has no shorted nets.\n")); + else + pcb_message(PCB_MSG_WARNING, _("Nothing more to add, but there are\n" + "either rat-lines in the layout, disabled nets\n" "in the net-list, or missing components\n")); + } + return (pcb_false); +} + +/* XXX: This is copied in large part from AddAllRats above; for + * maintainability, AddAllRats probably wants to be tweaked to use this + * version of the code so that we don't have duplication. */ +pcb_netlist_list_t pcb_rat_collect_subnets(pcb_bool SelectedOnly) +{ + pcb_netlist_list_t result = { 0, 0, NULL }; + pcb_netlist_t *Nets, *Wantlist; + pcb_net_t *lonesome; + pcb_connection_t *onepin; + + /* the netlist library has the text form + * ProcNetlist fills in the Netlist + * structure the way the final routing + * is supposed to look + */ + Wantlist = pcb_rat_proc_netlist(&(PCB->NetlistLib[PCB_NETLIST_EDITED])); + if (!Wantlist) { + pcb_message(PCB_MSG_WARNING, _("Can't add rat lines because no netlist is loaded.\n")); + return result; + } + /* initialize finding engine */ + pcb_conn_lookup_init(); + pcb_save_find_flag(PCB_FLAG_DRC); + /* now we build another netlist (Nets) for each + * net in Wantlist that shows how it actually looks now, + * then fill in any missing connections with rat lines. + * + * we first assume each connection is separate + * (no routing), then gather them into groups + * if the net is all routed, the new netlist (Nets) + * will have only one net entry. + * Note that DrawShortestRats consumes all nets + * from Nets, so *Nets is empty after the + * DrawShortestRats call + */ + PCB_NET_LOOP(Wantlist); + { + Nets = pcb_netlist_new(&result); + PCB_CONNECTION_LOOP(net); + { + if (!SelectedOnly || PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_pin_t *) connection->obj)) { + lonesome = pcb_net_new(Nets); + onepin = pcb_rat_connection_alloc(lonesome); + *onepin = *connection; + lonesome->Style = net->Style; + } + } + PCB_END_LOOP; + /* Note that AndRats is *pcb_false* here! */ + GatherSubnets(Nets, SelectedOnly, pcb_false); + } + PCB_END_LOOP; + pcb_conn_lookup_uninit(); + pcb_restore_find_flag(); + return result; +} + +/* + * Check to see if a particular name is the name of an already existing rats + * line + */ +static int rat_used(char *name) +{ + if (name == NULL) + return -1; + + PCB_MENU_LOOP(&(PCB->NetlistLib[PCB_NETLIST_EDITED])); + { + if (menu->Name && (strcmp(menu->Name, name) == 0)) + return 1; + } + PCB_END_LOOP; + + return 0; +} + +pcb_rat_t *pcb_rat_add_net(void) +{ + static int ratDrawn = 0; + char name1[256], *name2; + pcb_cardinal_t group1, group2; + char ratname[20]; + const char *rd; + int found; + void *ptr1, *ptr2, *ptr3; + pcb_lib_menu_t *menu; + pcb_lib_entry_t *entry; + + if (pcb_crosshair.AttachedLine.Point1.X == pcb_crosshair.AttachedLine.Point2.X + && pcb_crosshair.AttachedLine.Point1.Y == pcb_crosshair.AttachedLine.Point2.Y) + return (NULL); + + found = pcb_search_obj_by_location(PCB_TYPE_PAD | PCB_TYPE_PIN | PCB_TYPE_PSTK, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point1.X, pcb_crosshair.AttachedLine.Point1.Y, 5); + if (found == PCB_TYPE_NONE) { + pcb_message(PCB_MSG_ERROR, _("No pad/pin under rat line\n")); + return (NULL); + } + rd = get_refdes(ptr1); + if ((rd == NULL) || (*rd == 0) || (*rd == '<')) { + pcb_message(PCB_MSG_ERROR, _("You must name the starting element first\n")); + return (NULL); + } + + Sgrp = Cgrp = -1; + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &Sgrp, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &Cgrp, 1); + + /* will work for pins to since the FLAG is common */ + group1 = (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (pcb_pad_t *) ptr2) ? Sgrp : Cgrp); + strcpy(name1, pcb_connection_name(ptr2)); + found = pcb_search_obj_by_location(PCB_TYPE_PAD | PCB_TYPE_PIN, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point2.X, pcb_crosshair.AttachedLine.Point2.Y, 5); + if (found == PCB_TYPE_NONE) { + pcb_message(PCB_MSG_ERROR, _("No pad/pin under rat line\n")); + return (NULL); + } + rd = get_refdes(ptr1); + if ((rd == NULL) || (*rd == 0) || (*rd == '<')) { + pcb_message(PCB_MSG_ERROR, _("You must name the ending element first\n")); + return (NULL); + } + group2 = (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (pcb_pad_t *) ptr2) ? Sgrp : Cgrp); + name2 = pcb_connection_name(ptr2); + + menu = pcb_netnode_to_netname(name1); + if (menu) { + if (pcb_netnode_to_netname(name2)) { + pcb_message(PCB_MSG_ERROR, _("Both connections already in netlist - cannot merge nets\n")); + return (NULL); + } + entry = pcb_lib_entry_new(menu); + entry->ListEntry = pcb_strdup(name2); + entry->ListEntry_dontfree = 0; + pcb_netnode_to_netname(name2); + goto ratIt; + } + /* ok, the first name did not belong to a net */ + menu = pcb_netnode_to_netname(name2); + if (menu) { + entry = pcb_lib_entry_new(menu); + entry->ListEntry = pcb_strdup(name1); + entry->ListEntry_dontfree = 0; + pcb_netnode_to_netname(name1); + goto ratIt; + } + + /* + * neither belong to a net, so create a new one. + * + * before creating a new rats here, we need to search + * for a unique name. + */ + sprintf(ratname, " ratDrawn%i", ++ratDrawn); + while (rat_used(ratname)) { + sprintf(ratname, " ratDrawn%i", ++ratDrawn); + } + + menu = pcb_lib_menu_new(&(PCB->NetlistLib[PCB_NETLIST_EDITED]), NULL); + menu->Name = pcb_strdup(ratname); + entry = pcb_lib_entry_new(menu); + entry->ListEntry = pcb_strdup(name1); + entry->ListEntry_dontfree = 0; + + entry = pcb_lib_entry_new(menu); + entry->ListEntry = pcb_strdup(name2); + entry->ListEntry_dontfree = 0; + menu->flag = 1; + +ratIt: + pcb_netlist_changed(0); + return (pcb_rat_new(PCB->Data, pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + pcb_crosshair.AttachedLine.Point2.X, + pcb_crosshair.AttachedLine.Point2.Y, group1, group2, conf_core.appearance.rat_thickness, pcb_no_flags())); +} + + +char *pcb_connection_name(pcb_any_obj_t *obj) +{ + static char name[256]; + const char *num, *parent = NULL; + pcb_subc_t *subc; + + switch (obj->type) { + case PCB_OBJ_PIN: + num = ((pcb_pin_t *)obj)->Number; + parent = PCB_ELEM_NAME_REFDES((pcb_element_t*)((pcb_pin_t *)obj)->Element); + break; + case PCB_OBJ_PAD: + num = ((pcb_pad_t *)obj)->Number; + parent = PCB_ELEM_NAME_REFDES((pcb_element_t*)((pcb_pad_t *)obj)->Element); + break; + default: + if (obj->term == NULL) + return NULL; + num = obj->term; + subc = pcb_obj_parent_subc(obj); + if (subc != NULL) + parent = subc->refdes; + } + strcpy(name, PCB_UNKNOWN(parent)); + strcat(name, "-"); + strcat(name, PCB_UNKNOWN(num)); + return (name); +} + +/* --------------------------------------------------------------------------- + * get next slot for a connection, allocates memory if necessary + */ +pcb_connection_t *pcb_rat_connection_alloc(pcb_net_t *Net) +{ + pcb_connection_t *con = Net->Connection; + + /* realloc new memory if necessary and clear it */ + if (Net->ConnectionN >= Net->ConnectionMax) { + Net->ConnectionMax += STEP_POINT; + con = (pcb_connection_t *) realloc(con, Net->ConnectionMax * sizeof(pcb_connection_t)); + Net->Connection = con; + memset(con + Net->ConnectionN, 0, STEP_POINT * sizeof(pcb_connection_t)); + } + return (con + Net->ConnectionN++); +} Index: tags/1.2.7/src/rats.h =================================================================== --- tags/1.2.7/src/rats.h (nonexistent) +++ tags/1.2.7/src/rats.h (revision 13657) @@ -0,0 +1,80 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * + * rats.c, rats.h Copyright (C) 1997, 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_RATS_H +#define PCB_RATS_H + +#include "config.h" +#include "netlist.h" +#include "layer.h" +#include "layer_grp.h" + +struct pcb_connection_s { /* holds a connection (rat) */ + pcb_coord_t X, Y; /* coordinate of connection */ + void *ptr1; /* parent of ptr2??? */ + pcb_any_obj_t *obj; /* the object of the connection */ + pcb_layergrp_id_t group; /* the layer group of the connection */ + pcb_lib_menu_t *menu; /* the netmenu this *SHOULD* belong too */ +}; + + +pcb_rat_t *pcb_rat_add_net(void); + +/* Put the rats nest into the layout from the loaded netlist; if SelectedOnly + is pcb_true, it will only draw rats to selected pins and pads */ +pcb_bool pcb_rat_add_all(pcb_bool SelectedOnly, void (*funcp) (register pcb_connection_t *, register pcb_connection_t *, register pcb_route_style_t *)); + +char *pcb_connection_name(pcb_any_obj_t *obj); + + +/* Search a netlist menu entry and locate the corresponding pad returns + pcb_true if found, and fills in Connection information */ +pcb_bool pcb_rat_seek_pad(pcb_lib_entry_t * entry, pcb_connection_t * conn, pcb_bool Same); + + +/* Read the library-netlist and build a pcb_true Netlist structure */ +pcb_netlist_t *pcb_rat_proc_netlist(pcb_lib_t *net_menu); + +pcb_netlist_list_t pcb_rat_collect_subnets(pcb_bool SelectedOnly); + +pcb_connection_t *pcb_rat_connection_alloc(pcb_net_t *Net); + +#define PCB_CONNECTION_LOOP(net) do { \ + pcb_cardinal_t n; \ + pcb_connection_t * connection; \ + for (n = (net)->ConnectionN-1; n != -1; n--) \ + { \ + connection = & (net)->Connection[n] + +#define PCB_RAT_LOOP(top) do { \ + pcb_rat_t *line; \ + gdl_iterator_t __it__; \ + ratlist_foreach(&(top)->Rat, &__it__, line) { + + +#endif Index: tags/1.2.7/src/rats_act.c =================================================================== --- tags/1.2.7/src/rats_act.c (nonexistent) +++ tags/1.2.7/src/rats_act.c (revision 13657) @@ -0,0 +1,228 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "error.h" +#include "undo.h" +#include "find.h" +#include "remove.h" +#include "funchash_core.h" +#include "compat_nls.h" +#include "obj_rat.h" + +#include "rats.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."; + +/* %start-doc actions AddRats + +@table @code + +@item AllRats +Create rat lines for all loaded nets that aren't already connected on +with copper. + +@item 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. + +@end table + +%end-doc */ + +static int pcb_act_AddRats(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + pcb_rat_t *shorty; + float len, small; + + if (function) { + if (conf_core.temp.rat_warn) + pcb_clear_warnings(); + switch (pcb_funchash_get(function, NULL)) { + case F_AllRats: + if (pcb_rat_add_all(pcb_false, NULL)) + pcb_board_set_changed_flag(pcb_true); + break; + case F_SelectedRats: + case F_Selected: + if (pcb_rat_add_all(pcb_true, NULL)) + 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; + } + } + 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."; + +/* %start-doc actions Connection + +Connections found with this action will be highlighted in the +``connected-color'' color and will have the ``found'' flag set. + +@table @code + +@item Find +The net under the cursor is ``found''. + +@item ResetLinesAndPolygons +Any ``found'' lines and polygons are marked ``not found''. + +@item ResetPinsAndVias +Any ``found'' pins and vias are marked ``not found''. + +@item Reset +All ``found'' objects are marked ``not found''. + +@end table + +%end-doc */ + +static int pcb_act_Connection(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + switch (pcb_funchash_get(function, NULL)) { + case F_Find: + { + pcb_gui->get_coords(_("Click on a connection"), &x, &y); + pcb_lookup_conn(x, y, pcb_true, 1, PCB_FLAG_FOUND); + break; + } + + case F_ResetLinesAndPolygons: + if (pcb_reset_found_lines_polys(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + + case F_ResetPinsViasAndPads: + if (pcb_reset_found_pins_vias_pads(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + + case F_Reset: + if (pcb_reset_conns(pcb_true)) { + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + } + return 0; + } + + PCB_ACT_FAIL(Connection); +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_DeleteRats[] = "DeleteRats(AllRats|Selected|SelectedRats)"; + +static const char pcb_acth_DeleteRats[] = "Delete rat lines."; + +/* %start-doc actions DeleteRats + +%end-doc */ + +static int pcb_act_DeleteRats(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + if (conf_core.temp.rat_warn) + pcb_clear_warnings(); + switch (pcb_funchash_get(function, NULL)) { + 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; + } + } + return 0; +} + + +pcb_hid_action_t rats_action_list[] = { + {"AddRats", 0, pcb_act_AddRats, + pcb_acth_AddRats, pcb_acts_AddRats} + , + {"Connection", 0, pcb_act_Connection, + pcb_acth_Connection, pcb_acts_Connection} + , + {"DeleteRats", 0, pcb_act_DeleteRats, + pcb_acth_DeleteRats, pcb_acts_DeleteRats} +}; + +PCB_REGISTER_ACTIONS(rats_action_list, NULL) Index: tags/1.2.7/src/rats_patch.c =================================================================== --- tags/1.2.7/src/rats_patch.c (nonexistent) +++ tags/1.2.7/src/rats_patch.c (revision 13657) @@ -0,0 +1,496 @@ +/* + * 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. + * + */ + +#include "rats_patch.h" +#include "genht/htsp.h" +#include "genht/hash.h" + +#include "config.h" +#include "data.h" +#include "error.h" +#include "copy.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "safe_fs.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 void netlist_free(pcb_lib_t *dst) +{ + int n, p; + + if (dst->Menu == NULL) + return; + + for (n = 0; n < dst->MenuN; n++) { + pcb_lib_menu_t *dmenu = &dst->Menu[n]; + free(dmenu->Name); + for (p = 0; p < dmenu->EntryN; p++) { + pcb_lib_entry_t *dentry = &dmenu->Entry[p]; + free((char*)dentry->ListEntry); + } + free(dmenu->Entry); + } + free(dst->Menu); + dst->Menu = NULL; +} + +static void netlist_copy(pcb_lib_t *dst, pcb_lib_t *src) +{ + int n, p; + dst->MenuMax = dst->MenuN = src->MenuN; + if (src->MenuN != 0) { + dst->Menu = calloc(sizeof(pcb_lib_menu_t), dst->MenuN); + for (n = 0; n < src->MenuN; n++) { + pcb_lib_menu_t *smenu = &src->Menu[n]; + pcb_lib_menu_t *dmenu = &dst->Menu[n]; +/* fprintf(stderr, "Net %d name='%s': ", n, smenu->Name+2);*/ + dmenu->Name = pcb_strdup(smenu->Name); + dmenu->EntryMax = dmenu->EntryN = smenu->EntryN; + dmenu->Entry = calloc(sizeof(pcb_lib_entry_t), dmenu->EntryN); + dmenu->flag = smenu->flag; + dmenu->internal = smenu->internal; + for (p = 0; p < smenu->EntryN; p++) { + pcb_lib_entry_t *sentry = &smenu->Entry[p]; + pcb_lib_entry_t *dentry = &dmenu->Entry[p]; + dentry->ListEntry = pcb_strdup(sentry->ListEntry); + dentry->ListEntry_dontfree = 0; +/* fprintf (stderr, " '%s'/%p", dentry->ListEntry, dentry->ListEntry);*/ + } +/* fprintf(stderr, "\n");*/ + } + } + else + dst->Menu = NULL; +} + + +int rats_patch_apply_conn(pcb_board_t *pcb, pcb_ratspatch_line_t * patch, int del) +{ + int n; + + for (n = 0; n < pcb->NetlistLib[PCB_NETLIST_EDITED].MenuN; n++) { + pcb_lib_menu_t *menu = &pcb->NetlistLib[PCB_NETLIST_EDITED].Menu[n]; + if (strcmp(menu->Name + 2, patch->arg1.net_name) == 0) { + int p; + for (p = 0; p < menu->EntryN; p++) { + pcb_lib_entry_t *entry = &menu->Entry[p]; +/* fprintf (stderr, "C'%s'/%p '%s'/%p\n", entry->ListEntry, entry->ListEntry, patch->id, patch->id);*/ + if (strcmp(entry->ListEntry, patch->id) == 0) { + if (del) { + /* want to delete and it's on the list */ + memmove(&menu->Entry[p], &menu->Entry[p + 1], (menu->EntryN - p - 1) * sizeof(pcb_lib_entry_t)); + menu->EntryN--; + 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 */ + pcb_lib_conn_new(menu, (char *) patch->id); + return 0; + } + } + + /* couldn't find the net: create it */ + { + pcb_lib_menu_t *net = NULL; + net = pcb_lib_net_new(&pcb->NetlistLib[PCB_NETLIST_EDITED], patch->arg1.net_name, NULL); + if (net == NULL) + return 1; + pcb_lib_conn_new(net, (char *) patch->id); + } + return 0; +} + + +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: +#warning 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; + + netlist_free(&(pcb->NetlistLib[PCB_NETLIST_EDITED])); + netlist_copy(&(pcb->NetlistLib[PCB_NETLIST_EDITED]), &(pcb->NetlistLib[PCB_NETLIST_INPUT])); + for (n = pcb->NetlistPatches; n != NULL; n = n->next) + pcb_ratspatch_apply(pcb, n); +} + +static pcb_lib_menu_t *rats_patch_find_net(pcb_board_t *pcb, const char *netname, int listidx) +{ + int n; + + for (n = 0; n < pcb->NetlistLib[listidx].MenuN; n++) { + pcb_lib_menu_t *menu = &pcb->NetlistLib[listidx].Menu[n]; + if (strcmp(menu->Name + 2, netname) == 0) + return menu; + } + return NULL; +} + +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) { + pcb_lib_menu_t *net; + int p; + + net = rats_patch_find_net(pcb, n->arg1.net_name, PCB_NETLIST_INPUT); +/* printf("net: '%s' %p\n", n->arg1.net_name, (void *)net);*/ + if (net != NULL) { + htsp_set(seen, n->arg1.net_name, net); + cb(ctx, PCB_RPE_INFO_BEGIN, n->arg1.net_name, NULL, NULL); + for (p = 0; p < net->EntryN; p++) { + pcb_lib_entry_t *entry = &net->Entry[p]; + cb(ctx, PCB_RPE_INFO_TERMINAL, n->arg1.net_name, NULL, entry->ListEntry); + } + 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()\n"; + +static const char pcb_acth_ReplaceFootprint[] = "Replace the footprint of the selected components with the footprint specified."; + +static int pcb_act_ReplaceFootprint(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *a[4]; + const char *fpname; + int found = 0; + + /* check if we have elements selected and quit if not */ + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + found = 1; + break; + } + } + PCB_END_LOOP; + + if (!(found)) { + pcb_message(PCB_MSG_ERROR, "ReplaceFootprint works on selected elements, please select elements first!\n"); + return 1; + } + + /* fetch the name of the new footprint */ + if (argc == 0) { + fpname = pcb_gui->prompt_for("Footprint name", ""); + if (fpname == NULL) { + pcb_message(PCB_MSG_ERROR, "No footprint name supplied\n"); + return 1; + } + } + else + fpname = argv[0]; + + /* check if the footprint is available */ + a[0] = fpname; + a[1] = NULL; + if (pcb_act_LoadFootprint(1, a, x, y) != 0) { + pcb_message(PCB_MSG_ERROR, "Can't load footprint %s\n", fpname); + return 1; + } + + + /* action: replace selected elements */ + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + a[0] = fpname; + a[1] = element->Name[1].TextString; + a[2] = element->Name[2].TextString; + a[3] = NULL; + pcb_act_LoadFootprint(3, a, element->MarkX, element->MarkY); + pcb_buffer_copy_to_layout(PCB, element->MarkX, element->MarkY); + pcb_ratspatch_append_optimize(PCB, RATP_CHANGE_ATTRIB, a[1], "footprint", fpname); + pcb_element_remove(element); + } + } + PCB_END_LOOP; + return 0; +} + +static const char pcb_acts_SavePatch[] = "SavePatch(filename)"; + +static const char pcb_acth_SavePatch[] = "Save netlist patch for back annotation."; + +/* %start-doc actions SavePatch +Save netlist patch for back annotation. +%end-doc */ +static int pcb_act_SavePatch(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *fn; + FILE *f; + + if (argc < 1) { + 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", "patch", 0); + + free(default_file); + } + else + fn = argv[0]; + f = pcb_fopen(fn, "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Can't open netlist patch file %s for writing\n", fn); + return 1; + } + pcb_ratspatch_fexport(PCB, f, 0); + fclose(f); + return 0; +} + +pcb_hid_action_t rats_patch_action_list[] = { + {"ReplaceFootprint", 0, pcb_act_ReplaceFootprint, + pcb_acth_ReplaceFootprint, pcb_acts_ReplaceFootprint} + , + {"SavePatch", 0, pcb_act_SavePatch, + pcb_acth_SavePatch, pcb_acts_SavePatch} +}; + +PCB_REGISTER_ACTIONS(rats_patch_action_list, NULL) Index: tags/1.2.7/src/rats_patch.h =================================================================== --- tags/1.2.7/src/rats_patch.h (nonexistent) +++ tags/1.2.7/src/rats_patch.h (revision 13657) @@ -0,0 +1,94 @@ +/* + * 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. + * + */ + +#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/1.2.7/src/remove.c =================================================================== --- tags/1.2.7/src/remove.c (nonexistent) +++ tags/1.2.7/src/remove.c (revision 13657) @@ -0,0 +1,122 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* functions used to remove vias, pins ... */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "draw.h" +#include "remove.h" +#include "select.h" +#include "undo.h" +#include "obj_all_op.h" +#include "obj_pstk_op.h" + +static pcb_opfunc_t RemoveFunctions = { + pcb_lineop_remove, + pcb_textop_remove, + pcb_polyop_remove, + pcb_viaop_remove, + pcb_elemop_remove, + NULL, + NULL, + NULL, + pcb_lineop_remove_point, + pcb_polyop_remove_point, + pcb_arcop_remve, + 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, + pcb_viaop_destroy, + pcb_elemop_destroy, + NULL, + NULL, + NULL, + 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(void) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_true; + ctx.remove.destroy_target = NULL; + + if (pcb_selected_operation(PCB, PCB->Data, &RemoveFunctions, &ctx, pcb_false, PCB_TYPEMASK_ALL)) { + 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.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + ptr = pcb_object_operation(&RemoveFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3); + return (ptr); +} + +void *pcb_destroy_object(pcb_data_t *Target, int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = Target; + + return (pcb_object_operation(&DestroyFunctions, &ctx, Type, Ptr1, Ptr2, Ptr3)); +} Index: tags/1.2.7/src/remove.h =================================================================== --- tags/1.2.7/src/remove.h (nonexistent) +++ tags/1.2.7/src/remove.h (revision 13657) @@ -0,0 +1,46 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Remove objects from the board */ + +#ifndef PCB_REMOVE_H +#define PCB_REMOVE_H + +#include "config.h" + +#define PCB_REMOVE_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PSTK | PCB_TYPE_LINE_POINT | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | \ + PCB_TYPE_POLY_POINT | PCB_TYPE_POLY | PCB_TYPE_RATLINE | PCB_TYPE_ARC | PCB_TYPE_ARC_POINT) + +pcb_bool pcb_remove_selected(void); + +/* 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, int Type, void *Ptr1, void *Ptr2, void *Ptr3); + +#endif Index: tags/1.2.7/src/remove_act.c =================================================================== --- tags/1.2.7/src/remove_act.c (nonexistent) +++ tags/1.2.7/src/remove_act.c (revision 13657) @@ -0,0 +1,107 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ +#include "const.h" +#include "config.h" +#include "data.h" +#include "action_helper.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."; + +/* %start-doc actions Delete + +%end-doc */ + +static int pcb_act_Delete(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + int id = pcb_funchash_get(function, NULL); + + if (id == -1) { /* no arg */ + if (pcb_remove_selected() == pcb_false) + id = F_Object; + } + + switch (id) { + case F_Object: + pcb_gui->get_coords("Click on object to delete", &pcb_tool_note.X, &pcb_tool_note.Y); + pcb_crosshair_save_mode(); + pcb_crosshair_set_mode(PCB_MODE_REMOVE); + pcb_notify_mode(); + pcb_crosshair_restore_mode(); + break; + case F_Selected: + pcb_remove_selected(); + 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; + } + + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_RemoveSelected[] = "pcb_remove_selected()"; + +static const char pcb_acth_RemoveSelected[] = "Removes any selected objects."; + +/* %start-doc actions RemoveSelected + +%end-doc */ + +static int pcb_act_RemoveSelected(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (pcb_remove_selected()) + pcb_board_set_changed_flag(pcb_true); + return 0; +} + + +pcb_hid_action_t remove_action_list[] = { + {"Delete", 0, pcb_act_Delete, + pcb_acth_Delete, pcb_acts_Delete} + , + {"RemoveSelected", 0, pcb_act_RemoveSelected, + pcb_acth_RemoveSelected, pcb_acts_RemoveSelected} + , +}; + +PCB_REGISTER_ACTIONS(remove_action_list, NULL) Index: tags/1.2.7/src/rotate.c =================================================================== --- tags/1.2.7/src/rotate.c (nonexistent) +++ tags/1.2.7/src/rotate.c (revision 13657) @@ -0,0 +1,183 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* functions used to rotate pins, elements ... + */ + +#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 "compat_nls.h" +#include "obj_all_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_viaop_rotate90, + pcb_elemop_rotate90, + pcb_elemop_rotate90_name, + NULL, + NULL, + 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, + pcb_viaop_rotate, + NULL, + NULL, + NULL, + NULL, + 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_TYPE_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_TYPE_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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_arc_t *) ptr2)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + 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_TYPE_ELEMENT) + 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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_arc_t *) ptr2)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + 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_TYPE_ELEMENT) + 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/1.2.7/src/rotate.h =================================================================== --- tags/1.2.7/src/rotate.h (nonexistent) +++ tags/1.2.7/src/rotate.h (revision 13657) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_ROTATE_H +#define PCB_ROTATE_H + +#include "config.h" +#include "global_typedefs.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_TYPE_PSTK | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_ARC | PCB_TYPE_LINE_POINT | PCB_TYPE_LINE) + +/* 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 = px * cosa + py * sina; + ny = py * cosa - px * sina; + + *x = nx + cx; + *y = ny + cy; +} + +#endif Index: tags/1.2.7/src/route.c =================================================================== --- tags/1.2.7/src/route.c (nonexistent) +++ tags/1.2.7/src/route.c (revision 13657) @@ -0,0 +1,648 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#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 "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_TYPE_LINE; +} + +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_TYPE_ARC; +} + + +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; + } +} + + +/* 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 ) +{ + + /* TODO: If an external route calculator has been selected then use it instead of this default one. */ + /* TODO: Add DRC Checking */ + + + /* Set radius to 0 for standard 45/90 operation */ + const pcb_coord_t radius = thickness * conf_core.editor.route_radius; + + /* 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_direct(PCB,route,point1,point2,layer_id,thickness,clearance,flags); + return; + } + + /* Restart the route */ + pcb_route_reset(route); + route->start_point = *point1; + route->thickness = thickness; + route->clearance = clearance; + route->start_layer = layer_id; + route->end_layer = layer_id; + route->PCB = PCB; + route->flags = flags; + + /* 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; + } + } +} + +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; + char * number = (apply_to_line ? apply_to_line->Number : NULL); + + for( i=0;isize;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)); + + switch(p_obj->type) + { + case PCB_TYPE_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_TYPE_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_TYPE_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_TYPE_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, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_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) { + if(number) + line->Number = pcb_strdup(number); + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_line_invalidate_draw(layer, line); + pcb_undo_add_obj_to_create(PCB_TYPE_LINE, layer, line, line); + applied = 1; + } + } + break; + + case PCB_TYPE_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 ); + if(arc) { + pcb_added_lines++; + pcb_obj_add_attribs(arc, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_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); + + 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;isize;++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_TYPE_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_TYPE_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 * p_route->PCB->Bloat; + int i; + + pcb_gui->set_color(GC,conf_core.appearance.color.cross); + + for(i=0;isize;++i) { + const pcb_route_object_t * p_obj = &p_route->objects[i]; + + switch(p_obj->type) { + case PCB_TYPE_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_TYPE_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/1.2.7/src/route.h =================================================================== --- tags/1.2.7/src/route.h (nonexistent) +++ tags/1.2.7/src/route.h (revision 13657) @@ -0,0 +1,105 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef GUARD_PCB_RND_ROUTE_H +#define GUARD_PCB_RND_ROUTE_H + +#include "const.h" + +#define ROUTE_SMALL_DATA_SIZE 4 + +typedef struct { + pcb_obj_type_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_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_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); + +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 /* ! defined GUARD_PCB_RND_ROUTE_H */ Index: tags/1.2.7/src/route_style.c =================================================================== --- tags/1.2.7/src/route_style.c (nonexistent) +++ tags/1.2.7/src/route_style.c (revision 13657) @@ -0,0 +1,249 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#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" +#include "compat_nls.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; +} + + +/*! \brief Serializes the route style list + * \par Function Description + * Right now n_styles should always be set to NUM_STYLES, + * since that is the number of route styles pcb_route_string_parse() + * expects to parse. + */ +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/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_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 (cmp(Thick, styles->array[n].Thick)) continue; + if (cmp(Diameter, styles->array[n].Diameter)) continue; + if (cmp(Hole, styles->array[n].Hole)) continue; + if (cmp(Clearance, styles->array[n].Clearance)) continue; + if (cmps(Name, styles->array[n].name)) continue; + return n; + } + return -1; +} +#undef cmp +#undef cmps + + +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_TYPE_ELEMENT: /* we'd set pin/pad properties, so fall thru */ + case PCB_TYPE_VIA: + case PCB_TYPE_PIN: + return pcb_get_style_size(F_SelectedVias, out, 0, size_id); + case PCB_TYPE_PAD: + return pcb_get_style_size(F_SelectedPads, out, 0, size_id); + case PCB_TYPE_LINE: + return pcb_get_style_size(F_SelectedLines, out, 0, size_id); + case PCB_TYPE_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/1.2.7/src/route_style.h =================================================================== --- tags/1.2.7/src/route_style.h (nonexistent) +++ tags/1.2.7/src/route_style.h (revision 13657) @@ -0,0 +1,56 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#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); + +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/1.2.7/src/rtree.c =================================================================== --- tags/1.2.7/src/rtree.c (nonexistent) +++ tags/1.2.7/src/rtree.c (revision 13657) @@ -0,0 +1,1081 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 1998,1999,2000,2001,2002,2003,2004 harry eaton + * + * this file, rtree.c, was written and is + * 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 addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* implements r-tree structures. + * these should be much faster for the auto-router + * because the recursive search is much more efficient + * and that's where the auto-router spends all its time. + */ +#include "config.h" + +#include +#include +#include +#include + +#include "math_helper.h" +#include "compat_cc.h" +#include "rtree.h" +#include "obj_common.h" +#include "macro.h" + +#define SLOW_ASSERTS +/* All rectangles are closed on the bottom left and open on the + * top right. i.e. they contain one corner point, but not the other. + * This requires that the corner points not be equal! + */ + +#define M_SIZE PCB_RTREE_SIZE + +/* it seems that sorting the leaf order slows us down + * but sometimes gives better routes + */ +#undef SORT +#define SORT_NONLEAF + +#define DELETE_BY_POINTER + +typedef struct { + const pcb_box_t *bptr; /* pointer to the box */ + pcb_box_t bounds; /* copy of the box for locality of reference */ +} Rentry; + +struct rtree_node { + pcb_box_t box; /* bounds rectangle of this node */ + struct rtree_node *parent; /* parent of this node, NULL = root */ + struct { + unsigned is_leaf:1; /* this is a leaf node */ + unsigned manage:31; /* pcb_true==should free 'rect.bptr' if node is destroyed */ + } flags; + union { + struct rtree_node *kids[M_SIZE + 1]; /* when not leaf */ + Rentry rects[M_SIZE + 1]; /* when leaf */ + } u; +}; + +#ifndef NDEBUG +#ifdef SLOW_ASSERTS +static int __r_node_is_good(struct rtree_node *node) +{ + int i, flag = 1; + int kind = -1; + pcb_bool last = pcb_false; + + if (node == NULL) + return 1; + for (i = 0; i < M_SIZE; i++) { + if (node->flags.is_leaf) { + if (!node->u.rects[i].bptr) { + last = pcb_true; + continue; + } + /* check that once one entry is empty, all the rest are too */ + if (node->u.rects[i].bptr && last) + assert(0); + /* check that the box makes sense */ + if (node->box.X1 > node->box.X2) + assert(0); + if (node->box.Y1 > node->box.Y2) + assert(0); + /* check that bounds is the same as the pointer */ + if (node->u.rects[i].bounds.X1 != node->u.rects[i].bptr->X1) + assert(0); + if (node->u.rects[i].bounds.Y1 != node->u.rects[i].bptr->Y1) + assert(0); + if (node->u.rects[i].bounds.X2 != node->u.rects[i].bptr->X2) + assert(0); + if (node->u.rects[i].bounds.Y2 != node->u.rects[i].bptr->Y2) + assert(0); + /* check that entries are within node bounds */ + if (node->u.rects[i].bounds.X1 < node->box.X1) + assert(0); + if (node->u.rects[i].bounds.X2 > node->box.X2) + assert(0); + if (node->u.rects[i].bounds.Y1 < node->box.Y1) + assert(0); + if (node->u.rects[i].bounds.Y2 > node->box.Y2) + assert(0); + } + else { + if (!node->u.kids[i]) { + last = pcb_true; + continue; + } + /* make sure all children are the same type */ + if (kind == -1) + kind = node->u.kids[i]->flags.is_leaf; + else if (kind != node->u.kids[i]->flags.is_leaf) + assert(0); + /* check that once one entry is empty, all the rest are too */ + if (node->u.kids[i] && last) + assert(0); + /* check that entries are within node bounds */ + if (node->u.kids[i]->box.X1 < node->box.X1) + assert(0); + if (node->u.kids[i]->box.X2 > node->box.X2) + assert(0); + if (node->u.kids[i]->box.Y1 < node->box.Y1) + assert(0); + if (node->u.kids[i]->box.Y2 > node->box.Y2) + assert(0); + } + flag <<= 1; + } + /* check that we're completely in the parent's bounds */ + if (node->parent) { + if (node->parent->box.X1 > node->box.X1) + assert(0); + if (node->parent->box.X2 < node->box.X2) + assert(0); + if (node->parent->box.Y1 > node->box.Y1) + assert(0); + if (node->parent->box.Y2 < node->box.Y2) + assert(0); + } + /* make sure overflow is empty */ + if (!node->flags.is_leaf && node->u.kids[i]) + assert(0); + if (node->flags.is_leaf && node->u.rects[i].bptr) + assert(0); + return 1; +} + +/* check the whole tree from this node down for consistency */ +static pcb_bool __r_tree_is_good(struct rtree_node *node) +{ + int i; + + if (!node) + return 1; + if (!__r_node_is_good(node)) + assert(0); + if (node->flags.is_leaf) + return 1; + for (i = 0; i < M_SIZE; i++) { + if (!__r_tree_is_good(node->u.kids[i])) + return 0; + } + return 1; +} +#endif +#endif + +#ifndef NDEBUG +/* print out the tree */ +void pcb_r_dump_tree(struct rtree_node *node, int depth) +{ + int i, j; + static int count; + static double area; + + if (depth == 0) { + area = 0; + count = 0; + } + area += (node->box.X2 - node->box.X1) * (double) (node->box.Y2 - node->box.Y1); + count++; + for (i = 0; i < depth; i++) + printf(" "); + if (!node->flags.is_leaf) { + printf("p=0x%p node X(%d, %d) Y(%d, %d)\n", (void *) node, node->box.X1, node->box.X2, node->box.Y1, node->box.Y2); + } + else { + printf("p=0x%p leaf manage(%02x) X(%d, %d) Y(%d, %d)\n", (void *) node, + node->flags.manage, node->box.X1, node->box.X2, node->box.Y1, node->box.Y2); + for (j = 0; j < M_SIZE; j++) { + if (!node->u.rects[j].bptr) + break; + area += + (node->u.rects[j].bounds.X2 - + node->u.rects[j].bounds.X1) * (double) (node->u.rects[j].bounds.Y2 - node->u.rects[j].bounds.Y1); + count++; + for (i = 0; i < depth + 1; i++) + printf(" "); + printf("entry 0x%p X(%d, %d) Y(%d, %d)\n", + (void *) (node->u.rects[j].bptr), + node->u.rects[j].bounds.X1, node->u.rects[j].bounds.X2, node->u.rects[j].bounds.Y1, node->u.rects[j].bounds.Y2); + } + return; + } + for (i = 0; i < M_SIZE; i++) + if (node->u.kids[i]) + pcb_r_dump_tree(node->u.kids[i], depth + 1); + if (depth == 0) + printf("average box area is %g\n", area / count); +} +#endif + +/* Sort the children or entries of a node + * according to the largest side. + */ +#ifdef SORT +static int cmp_box(const pcb_box_t * a, const pcb_box_t * b) +{ + /* compare two box coordinates so that the __r_search + * will fail at the earliest comparison possible. + * It needs to see the biggest X1 first, then the + * smallest X2, the biggest Y1 and smallest Y2 + */ + if (a->X1 < b->X1) + return 0; + if (a->X1 > b->X1) + return 1; + if (a->X2 > b->X2) + return 0; + if (a->X2 < b->X2) + return 1; + if (a->Y1 < b->Y1) + return 0; + if (a->Y1 > b->Y1) + return 1; + if (a->Y2 > b->Y2) + return 0; + return 1; +} + +static void sort_node(struct rtree_node *node) +{ + if (node->flags.is_leaf) { + register Rentry *r, *i, temp; + + for (r = &node->u.rects[1]; r->bptr; r++) { + temp = *r; + i = r - 1; + while (i >= &node->u.rects[0]) { + if (cmp_box(&i->bounds, &r->bounds)) + break; + *(i + 1) = *i; + i--; + } + *(i + 1) = temp; + } + } +#ifdef SORT_NONLEAF + else { + register struct rtree_node **r, **i, *temp; + + for (r = &node->u.kids[1]; *r; r++) { + temp = *r; + i = r - 1; + while (i >= &node->u.kids[0]) { + if (cmp_box(&(*i)->box, &(*r)->box)) + break; + *(i + 1) = *i; + i--; + } + *(i + 1) = temp; + } + } +#endif +} +#else +#define sort_node(x) +#endif + +/* set the node bounds large enough to encompass all + * of the children's rectangles + */ +static void adjust_bounds(struct rtree_node *node) +{ + int i; + + assert(node); + assert(node->u.kids[0]); + if (node->flags.is_leaf) { + node->box = node->u.rects[0].bounds; + for (i = 1; i < M_SIZE + 1; i++) { + if (!node->u.rects[i].bptr) + return; + PCB_MAKE_MIN(node->box.X1, node->u.rects[i].bounds.X1); + PCB_MAKE_MAX(node->box.X2, node->u.rects[i].bounds.X2); + PCB_MAKE_MIN(node->box.Y1, node->u.rects[i].bounds.Y1); + PCB_MAKE_MAX(node->box.Y2, node->u.rects[i].bounds.Y2); + } + } + else { + node->box = node->u.kids[0]->box; + for (i = 1; i < M_SIZE + 1; i++) { + if (!node->u.kids[i]) + return; + PCB_MAKE_MIN(node->box.X1, node->u.kids[i]->box.X1); + PCB_MAKE_MAX(node->box.X2, node->u.kids[i]->box.X2); + PCB_MAKE_MIN(node->box.Y1, node->u.kids[i]->box.Y1); + PCB_MAKE_MAX(node->box.Y2, node->u.kids[i]->box.Y2); + } + } +} + +/* create an r-tree from an unsorted list of boxes. + * the r-tree will keep pointers into + * it, so don't free the box list until you've called r_destroy_tree. + * if you set 'manage' to pcb_true, r_destroy_tree will free your boxlist. + */ +pcb_rtree_t *pcb_r_create_tree(const pcb_box_t * boxlist[], int N, int manage) +{ + pcb_rtree_t *rtree; + struct rtree_node *node; + int i; + + assert(N >= 0); + rtree = (pcb_rtree_t *) calloc(1, sizeof(*rtree)); + /* start with a single empty leaf node */ + node = (struct rtree_node *) calloc(1, sizeof(*node)); + node->flags.is_leaf = 1; + node->parent = NULL; + rtree->root = node; + /* simple, just insert all of the boxes! */ + for (i = 0; i < N; i++) { + assert(boxlist[i]); + pcb_r_insert_entry(rtree, boxlist[i], manage); + } +#ifdef SLOW_ASSERTS + assert(__r_tree_is_good(rtree->root)); +#endif + return rtree; +} + +static void __r_destroy_tree(struct rtree_node *node) +{ + int i, flag = 1; + + if (node->flags.is_leaf) + for (i = 0; i < M_SIZE; i++) { + if (!node->u.rects[i].bptr) + break; + if (node->flags.manage & flag) + free((void *) node->u.rects[i].bptr); + flag = flag << 1; + } + else + for (i = 0; i < M_SIZE; i++) { + if (!node->u.kids[i]) + break; + __r_destroy_tree(node->u.kids[i]); + } + free(node); +} + +/* free the memory associated with an rtree. */ +void pcb_r_destroy_tree(pcb_rtree_t ** rtree) +{ + + __r_destroy_tree((*rtree)->root); + free(*rtree); + *rtree = NULL; +} + +typedef struct { + pcb_r_dir_t (*check_it) (const pcb_box_t * region, void *cl); + pcb_r_dir_t (*found_it) (const pcb_box_t * box, void *cl); + void *closure; + int cancel; +} r_arg; + +/* most of the auto-routing time is spent in this routine + * so some careful thought has been given to maximizing the speed + * + */ +int __r_search(struct rtree_node *node, const pcb_box_t * query, r_arg * arg) +{ + pcb_r_dir_t res; + + assert(node); + /** assert that starting_region is well formed */ + assert(query->X1 <= query->X2 && query->Y1 <= query->Y2); + assert(node->box.X1 < query->X2 && node->box.X2 > query->X1 && node->box.Y1 < query->Y2 && node->box.Y2 > query->Y1); +#ifdef SLOW_ASSERTS + /** assert that node is well formed */ + assert(__r_node_is_good(node)); +#endif + /* the check for bounds is done before entry. This saves the overhead + * of building/destroying the stack frame for each bounds that fails + * to intersect, which is the most common condition. + */ + if (node->flags.is_leaf) { + register int i; + if (arg->found_it) { /* test this once outside of loop */ + register int seen = 0; + for (i = 0; node->u.rects[i].bptr; i++) { + if ((node->u.rects[i].bounds.X1 < query->X2) && + (node->u.rects[i].bounds.X2 > query->X1) && + (node->u.rects[i].bounds.Y1 < query->Y2) && + (node->u.rects[i].bounds.Y2 > query->Y1)) { + res = arg->found_it(node->u.rects[i].bptr, arg->closure); + if (res == PCB_R_DIR_CANCEL) { + arg->cancel = 1; + return seen; + } + if (res != PCB_R_DIR_NOT_FOUND) + seen++; + } + } + return seen; + } + else { + register int seen = 0; + for (i = 0; node->u.rects[i].bptr; i++) { + if ((node->u.rects[i].bounds.X1 < query->X2) && + (node->u.rects[i].bounds.X2 > query->X1) && + (node->u.rects[i].bounds.Y1 < query->Y2) && (node->u.rects[i].bounds.Y2 > query->Y1)) + seen++; + } + return seen; + } + } + + /* not a leaf, recurse on lower nodes */ + if (arg->check_it != NULL) { + int seen = 0; + struct rtree_node **n; + for (n = &node->u.kids[0]; *n; n++) { + if ((*n)->box.X1 >= query->X2 || + (*n)->box.X2 <= query->X1 || + (*n)->box.Y1 >= query->Y2 || (*n)->box.Y2 <= query->Y1) + continue; + res = arg->check_it(&(*n)->box, arg->closure); + if (res == PCB_R_DIR_CANCEL) { + arg->cancel = 1; + return seen; + } + if (!res) + continue; + seen += __r_search(*n, query, arg); + if (arg->cancel) + break; + } + return seen; + } + else { + int seen = 0; + struct rtree_node **n; + for (n = &node->u.kids[0]; *n; n++) { + if ((*n)->box.X1 >= query->X2 || (*n)->box.X2 <= query->X1 || (*n)->box.Y1 >= query->Y2 || (*n)->box.Y2 <= query->Y1) + continue; + seen += __r_search(*n, query, arg); + if (arg->cancel) + break; + } + return seen; + } +} + +/* Parameterized search in the rtree. + * Sets num_found to the number of rectangles found. + * calls found_rectangle for each intersection seen + * and calls check_region with the current sub-region + * to see whether deeper searching is desired + * Returns how the search ended. + */ +pcb_r_dir_t +pcb_r_search(pcb_rtree_t * rtree, const pcb_box_t * query, + pcb_r_dir_t (*check_region) (const pcb_box_t * region, void *cl), + pcb_r_dir_t (*found_rectangle) (const pcb_box_t * box, void *cl), void *cl, + int *num_found) +{ + r_arg arg; + int res = 0; + + arg.cancel = 0; + + if (!rtree || rtree->size < 1) + goto ret; + if (query) { +#ifdef SLOW_ASSERTS + assert(__r_tree_is_good(rtree->root)); +#endif +#ifdef DEBUG + if (query->X2 <= query->X1 || query->Y2 <= query->Y1) + goto ret; +#endif + /* check this box. If it's not touched we're done here */ + if (rtree->root->box.X1 >= query->X2 || + rtree->root->box.X2 <= query->X1 || rtree->root->box.Y1 >= query->Y2 || rtree->root->box.Y2 <= query->Y1) + goto ret; + arg.check_it = check_region; + arg.found_it = found_rectangle; + arg.closure = cl; + + res = __r_search(rtree->root, query, &arg); + } + else { + arg.check_it = check_region; + arg.found_it = found_rectangle; + arg.closure = cl; + res = __r_search(rtree->root, &rtree->root->box, &arg); + } + +ret:; + if (num_found != NULL) + *num_found = res; + if (arg.cancel) + return PCB_R_DIR_CANCEL; + if (res == 0) + return PCB_R_DIR_NOT_FOUND; + return PCB_R_DIR_FOUND_CONTINUE; +} + +/*------ r_region_is_empty ------*/ +static pcb_r_dir_t __r_region_is_empty_rect_in_reg(const pcb_box_t * box, void *cl) +{ + jmp_buf *envp = (jmp_buf *) cl; + longjmp(*envp, 1); /* found one! */ +} + +/* 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) +{ + jmp_buf env; + int r; + + if (setjmp(env)) + return 0; + pcb_r_search(rtree, region, NULL, __r_region_is_empty_rect_in_reg, &env, &r); + assert(r == 0); /* otherwise longjmp would have been called */ + return 1; /* no rectangles found */ +} + +struct centroid { + float x, y, area; +}; + +/* split the node into two nodes putting clusters in each + * use the k-means clustering algorithm + */ +struct rtree_node *find_clusters(struct rtree_node *node) +{ + float total_a, total_b; + float a_X, a_Y, b_X, b_Y; + pcb_bool belong[M_SIZE + 1]; + struct centroid center[M_SIZE + 1]; + int clust_a, clust_b, tries; + int a_manage = 0, b_manage = 0; + int i, old_ax, old_ay, old_bx, old_by; + struct rtree_node *new_node; + pcb_box_t *b; + + for (i = 0; i < M_SIZE + 1; i++) { + if (node->flags.is_leaf) + b = &(node->u.rects[i].bounds); + else + b = &(node->u.kids[i]->box); + center[i].x = 0.5 * (b->X1 + b->X2); + center[i].y = 0.5 * (b->Y1 + b->Y2); + /* adding 1 prevents zero area */ + center[i].area = 1. + (float) (b->X2 - b->X1) * (float) (b->Y2 - b->Y1); + } + /* starting 'A' cluster center */ + a_X = center[0].x; + a_Y = center[0].y; + /* starting 'B' cluster center */ + b_X = center[M_SIZE].x; + b_Y = center[M_SIZE].y; + /* don't allow the same cluster centers */ + if (b_X == a_X && b_Y == a_Y) { + b_X += 10000; + a_Y -= 10000; + } + for (tries = 0; tries < M_SIZE; tries++) { + old_ax = (int) a_X; + old_ay = (int) a_Y; + old_bx = (int) b_X; + old_by = (int) b_Y; + clust_a = clust_b = 0; + for (i = 0; i < M_SIZE + 1; i++) { + float dist1, dist2; + + dist1 = PCB_SQUARE(a_X - center[i].x) + PCB_SQUARE(a_Y - center[i].y); + dist2 = PCB_SQUARE(b_X - center[i].x) + PCB_SQUARE(b_Y - center[i].y); + if (dist1 * (clust_a + M_SIZE / 2) < dist2 * (clust_b + M_SIZE / 2)) { + belong[i] = pcb_true; + clust_a++; + } + else { + belong[i] = pcb_false; + clust_b++; + } + } + /* kludge to fix degenerate cases */ + if (clust_a == M_SIZE + 1) + belong[M_SIZE / 2] = pcb_false; + else if (clust_b == M_SIZE + 1) + belong[M_SIZE / 2] = pcb_true; + /* compute new center of gravity of clusters */ + total_a = total_b = 0; + a_X = a_Y = b_X = b_Y = 0; + for (i = 0; i < M_SIZE + 1; i++) { + if (belong[i]) { + a_X += center[i].x * center[i].area; + a_Y += center[i].y * center[i].area; + total_a += center[i].area; + } + else { + b_X += center[i].x * center[i].area; + b_Y += center[i].y * center[i].area; + total_b += center[i].area; + } + } + a_X /= total_a; + a_Y /= total_a; + b_X /= total_b; + b_Y /= total_b; + if (old_ax == (int) a_X && old_ay == (int) a_Y && old_bx == (int) b_X && old_by == (int) b_Y) + break; + } + /* Now 'belong' has the partition map */ + new_node = (struct rtree_node *) calloc(1, sizeof(*new_node)); + new_node->parent = node->parent; + new_node->flags.is_leaf = node->flags.is_leaf; + clust_a = clust_b = 0; + if (node->flags.is_leaf) { + int flag, a_flag, b_flag; + flag = a_flag = b_flag = 1; + for (i = 0; i < M_SIZE + 1; i++) { + if (belong[i]) { + node->u.rects[clust_a++] = node->u.rects[i]; + if (node->flags.manage & flag) + a_manage |= a_flag; + a_flag <<= 1; + } + else { + new_node->u.rects[clust_b++] = node->u.rects[i]; + if (node->flags.manage & flag) + b_manage |= b_flag; + b_flag <<= 1; + } + flag <<= 1; + } + } + else { + for (i = 0; i < M_SIZE + 1; i++) { + if (belong[i]) + node->u.kids[clust_a++] = node->u.kids[i]; + else { + node->u.kids[i]->parent = new_node; + new_node->u.kids[clust_b++] = node->u.kids[i]; + } + } + } + node->flags.manage = a_manage; + new_node->flags.manage = b_manage; + assert(clust_a != 0); + assert(clust_b != 0); + if (node->flags.is_leaf) + for (; clust_a < M_SIZE + 1; clust_a++) + node->u.rects[clust_a].bptr = NULL; + else + for (; clust_a < M_SIZE + 1; clust_a++) + node->u.kids[clust_a] = NULL; + adjust_bounds(node); + sort_node(node); + adjust_bounds(new_node); + sort_node(new_node); + return (new_node); +} + +/* split a node according to clusters + */ +static void split_node(struct rtree_node *node) +{ + int i; + struct rtree_node *new_node; + + assert(node); + assert(node->flags.is_leaf ? (void *) node->u.rects[M_SIZE].bptr : (void *) node->u.kids[M_SIZE]); + new_node = find_clusters(node); + if (node->parent == NULL) { /* split root node */ + struct rtree_node *second; + + second = (struct rtree_node *) calloc(1, sizeof(*second)); + *second = *node; + if (!second->flags.is_leaf) + for (i = 0; i < M_SIZE; i++) + if (second->u.kids[i]) + second->u.kids[i]->parent = second; + node->flags.is_leaf = 0; + node->flags.manage = 0; + second->parent = new_node->parent = node; + node->u.kids[0] = new_node; + node->u.kids[1] = second; + for (i = 2; i < M_SIZE + 1; i++) + node->u.kids[i] = NULL; + adjust_bounds(node); + sort_node(node); +#ifdef SLOW_ASSERTS + assert(__r_tree_is_good(node)); +#endif + return; + } + for (i = 0; i < M_SIZE; i++) + if (!node->parent->u.kids[i]) + break; + node->parent->u.kids[i] = new_node; +#ifdef SLOW_ASSERTS + assert(__r_node_is_good(node)); + assert(__r_node_is_good(new_node)); +#endif + if (i < M_SIZE) { +#ifdef SLOW_ASSERTS + assert(__r_node_is_good(node->parent)); +#endif + sort_node(node->parent); + return; + } + split_node(node->parent); +} + +static inline int contained(struct rtree_node *node, const pcb_box_t * query) +{ + if (node->box.X1 > query->X1 || node->box.X2 < query->X2 || node->box.Y1 > query->Y1 || node->box.Y2 < query->Y2) + return 0; + return 1; +} + + +static inline double penalty(struct rtree_node *node, const pcb_box_t * query) +{ + double score; + + /* Compute the area penalty for inserting here and return. + * The penalty is the increase in area necessary + * to include the query-> + */ + score = (MAX(node->box.X2, query->X2) - MIN(node->box.X1, query->X1)); + score *= (MAX(node->box.Y2, query->Y2) - MIN(node->box.Y1, query->Y1)); + score -= (double) (node->box.X2 - node->box.X1) * (double) (node->box.Y2 - node->box.Y1); + return score; +} + +static void __r_insert_node(struct rtree_node *node, const pcb_box_t * query, int manage, pcb_bool force) +{ + +#ifdef SLOW_ASSERTS + assert(__r_node_is_good(node)); +#endif + /* Ok, at this point we must already enclose the query or we're forcing + * this node to expand to enclose it, so if we're a leaf, simply store + * the query here + */ + + if (node->flags.is_leaf) { + register int i; + + if (PCB_UNLIKELY(manage)) { + register int flag = 1; + + for (i = 0; i < M_SIZE; i++) { + if (!node->u.rects[i].bptr) + break; + flag <<= 1; + } + node->flags.manage |= flag; + } + else { + for (i = 0; i < M_SIZE; i++) + if (!node->u.rects[i].bptr) + break; + } + /* the node always has an extra space available */ + node->u.rects[i].bptr = query; + node->u.rects[i].bounds = *query; + /* first entry in node determines initial bounding box */ + if (i == 0) + node->box = *query; + else if (force) { + PCB_MAKE_MIN(node->box.X1, query->X1); + PCB_MAKE_MAX(node->box.X2, query->X2); + PCB_MAKE_MIN(node->box.Y1, query->Y1); + PCB_MAKE_MAX(node->box.Y2, query->Y2); + } + if (i < M_SIZE) { + sort_node(node); + return; + } + /* we must split the node */ + split_node(node); + return; + } + else { + int i; + struct rtree_node *best_node; + double score, best_score; + + if (force) { + PCB_MAKE_MIN(node->box.X1, query->X1); + PCB_MAKE_MAX(node->box.X2, query->X2); + PCB_MAKE_MIN(node->box.Y1, query->Y1); + PCB_MAKE_MAX(node->box.Y2, query->Y2); + } + + /* this node encloses it, but it's not a leaf, so descend the tree */ + + /* First check if any children actually encloses it */ + assert(node->u.kids[0]); + for (i = 0; i < M_SIZE; i++) { + if (!node->u.kids[i]) + break; + if (contained(node->u.kids[i], query)) { + __r_insert_node(node->u.kids[i], query, manage, pcb_false); + sort_node(node); + return; + } + } + + /* see if there is room for a new leaf node */ + if (node->u.kids[0]->flags.is_leaf && i < M_SIZE) { + struct rtree_node *new_node; + new_node = (struct rtree_node *) calloc(1, sizeof(*new_node)); + new_node->parent = node; + new_node->flags.is_leaf = pcb_true; + node->u.kids[i] = new_node; + new_node->u.rects[0].bptr = query; + new_node->u.rects[0].bounds = *query; + new_node->box = *query; + if (PCB_UNLIKELY(manage)) + new_node->flags.manage = 1; + sort_node(node); + return; + } + + /* Ok, so we're still here - look for the best child to push it into */ + best_score = penalty(node->u.kids[0], query); + best_node = node->u.kids[0]; + for (i = 1; i < M_SIZE; i++) { + if (!node->u.kids[i]) + break; + score = penalty(node->u.kids[i], query); + if (score < best_score) { + best_score = score; + best_node = node->u.kids[i]; + } + } + __r_insert_node(best_node, query, manage, pcb_true); + sort_node(node); + return; + } +} + +void pcb_r_insert_entry(pcb_rtree_t * rtree, const pcb_box_t * which, int man) +{ + assert(which); + assert(which->X1 <= which->X2); + assert(which->Y1 <= which->Y2); + /* recursively search the tree for the best leaf node */ + assert(rtree->root); + __r_insert_node(rtree->root, which, man, + rtree->root->box.X1 > which->X1 + || rtree->root->box.X2 < which->X2 || rtree->root->box.Y1 > which->Y1 || rtree->root->box.Y2 < which->Y2); + rtree->size++; +} + +pcb_bool __r_delete(struct rtree_node *node, const pcb_box_t * query) +{ + int i, flag, mask, a; + + /* the tree might be inconsistent during delete */ + if (query->X1 < node->box.X1 || query->Y1 < node->box.Y1 || query->X2 > node->box.X2 || query->Y2 > node->box.Y2) + return pcb_false; + if (!node->flags.is_leaf) { + for (i = 0; i < M_SIZE; i++) { + /* if this is us being removed, free and copy over */ + if (node->u.kids[i] == (struct rtree_node *) query) { + free((void *) query); + for (; i < M_SIZE; i++) { + node->u.kids[i] = node->u.kids[i + 1]; + if (!node->u.kids[i]) + break; + } + /* nobody home here now ? */ + if (!node->u.kids[0]) { + if (!node->parent) { + /* wow, the root is empty! */ + node->flags.is_leaf = 1; + /* changing type of node, be sure it's all zero */ + for (i = 1; i < M_SIZE + 1; i++) + node->u.rects[i].bptr = NULL; + return pcb_true; + } + return (__r_delete(node->parent, &node->box)); + } + else + /* propagate boundary adjust upward */ + while (node) { + adjust_bounds(node); + node = node->parent; + } + return pcb_true; + } + if (node->u.kids[i]) { + if (__r_delete(node->u.kids[i], query)) + return pcb_true; + } + else + break; + } + return pcb_false; + } + /* leaf node here */ + mask = 0; + a = 1; + for (i = 0; i < M_SIZE; i++) { +#ifdef DELETE_BY_POINTER + if (!node->u.rects[i].bptr || node->u.rects[i].bptr == query) +#else + if (node->u.rects[i].bounds.X1 == query->X1 && + node->u.rects[i].bounds.X2 == query->X2 && + node->u.rects[i].bounds.Y1 == query->Y1 && node->u.rects[i].bounds.Y2 == query->Y2) +#endif + break; + mask |= a; + a <<= 1; + } + if (!node->u.rects[i].bptr) + return pcb_false; /* not at this leaf */ + if (node->flags.manage & a) { + free((void *) node->u.rects[i].bptr); + node->u.rects[i].bptr = NULL; + } + /* squeeze the manage flags together */ + flag = node->flags.manage & mask; + mask = (~mask) << 1; + node->flags.manage = flag | ((node->flags.manage & mask) >> 1); + /* remove the entry */ + for (; i < M_SIZE; i++) { + node->u.rects[i] = node->u.rects[i + 1]; + if (!node->u.rects[i].bptr) + break; + } + if (!node->u.rects[0].bptr) { + if (node->parent) + __r_delete(node->parent, &node->box); + return pcb_true; + } + else + /* propagate boundary adjustment upward */ + while (node) { + adjust_bounds(node); + node = node->parent; + } + return pcb_true; +} + +pcb_bool pcb_r_delete_entry(pcb_rtree_t * rtree, const pcb_box_t * box) +{ + pcb_bool r; + + assert(box); + assert(rtree); + r = __r_delete(rtree->root, box); + if (r) + rtree->size--; +#ifdef SLOW_ASSERTS + assert(__r_tree_is_good(rtree->root)); +#endif + return r; +} + + +static pcb_box_t *pcb_r_next_(pcb_rtree_it_t *it, struct rtree_node *curr) +{ + int n; + + /* as long as we have boxes ready, ignore the tree */ + if (it->num_ready > 0) { +/* printf("rdy1 get [%d]: %p\n", it->num_ready-1, it->ready[it->num_ready-1]);*/ + return it->ready[--it->num_ready]; + } + + if (curr == NULL) { + + got_filled:; + + /* Next: get an element from the open list */ + if (it->used <= 0) + return NULL; + + curr = it->open[--it->used]; +/* printf("open get [%d]: %p\n", it->used, curr);*/ + } + + if (curr->flags.is_leaf) { + /* current is leaf: copy children to the ready list and return the first */ + for(it->num_ready = 0; it->num_ready < M_SIZE; it->num_ready++) { + if (curr->u.rects[it->num_ready].bptr == NULL) + break; + it->ready[it->num_ready] = (pcb_box_t *)curr->u.rects[it->num_ready].bptr; +/* printf("rdy add [%d]: %p\n", it->num_ready, it->ready[it->num_ready]);*/ + } + if (it->num_ready > 0) { +/* printf("rdy2 get [%d]: %p\n", it->num_ready-1, it->ready[it->num_ready-1]);*/ + return it->ready[--it->num_ready]; + } + + /* empty leaf: ignore */ + curr = NULL; + goto got_filled; + } + + /* current is a level, add to the open list and retry until a leaf is found */ + for(n = 0; n < M_SIZE; n++) { + if (curr->u.kids[n] != NULL) { + if (it->used >= it->alloced) { + it->alloced += 128; + it->open = realloc(it->open, it->alloced * sizeof(struct rtree_node *)); + } + it->open[it->used] = curr->u.kids[n]; +/* printf("open add [%d]: %p\n", it->used, it->open[it->used]);*/ + it->used++; + } + } + goto got_filled; +} + +pcb_box_t *pcb_r_first(pcb_rtree_t *tree, pcb_rtree_it_t *it) +{ + it->open = NULL; + it->alloced = it->used = 0; + it->num_ready = 0; + if (tree == NULL) + return NULL; + return pcb_r_next_(it, tree->root); +} + +pcb_box_t *pcb_r_next(pcb_rtree_it_t *it) +{ + return pcb_r_next_(it, NULL); +} + +void pcb_r_end(pcb_rtree_it_t *it) +{ + free(it->open); + it->open = NULL; + it->alloced = it->used = 0; +} + Index: tags/1.2.7/src/rtree.h =================================================================== --- tags/1.2.7/src/rtree.h (nonexistent) +++ tags/1.2.7/src/rtree.h (revision 13657) @@ -0,0 +1,113 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* r-tree: efficient lookup of screenobjects */ + +#ifndef PCB_RTREE_H +#define PCB_RTREE_H + +#include "global_typedefs.h" + +struct pcb_rtree_s { + struct rtree_node *root; + int size; /* number of entries in tree */ +}; + +/* the number of entries in each rtree node + * 4 - 7 seem to be pretty good settings + */ +#define PCB_RTREE_SIZE 6 + + +struct pcb_rtree_it_s { + struct rtree_node **open; + int used, alloced; + pcb_box_t *ready[PCB_RTREE_SIZE + 1]; + int num_ready; +}; + +/* 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 /* cancel the search and return immediately */ +} pcb_r_dir_t; + +/* create an rtree from the list of boxes. if 'manage' is pcb_true, then + * the tree will take ownership of 'boxlist' and free it when the tree + * is destroyed. */ +pcb_rtree_t *pcb_r_create_tree(const pcb_box_t * boxlist[], int N, int manage); +/* destroy an rtree */ +void pcb_r_destroy_tree(pcb_rtree_t ** rtree); + +pcb_bool pcb_r_delete_entry(pcb_rtree_t * rtree, const pcb_box_t * which); +void pcb_r_insert_entry(pcb_rtree_t * rtree, const pcb_box_t * which, int manage); + +/* generic search routine */ +/* region_in_search should return pcb_true if "what you're looking for" is + * within the specified region; regions, like rectangles, are closed on + * top and left and open on bottom and right. + * 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 * 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); + +/* -- special-purpose searches build upon r_search -- */ +/* 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(struct rtree_node *, int); + +#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 */ +void pcb_r_end(pcb_rtree_it_t *it); + + +#endif Index: tags/1.2.7/src/safe_fs.c =================================================================== --- tags/1.2.7/src/safe_fs.c (nonexistent) +++ tags/1.2.7/src/safe_fs.c (revision 13657) @@ -0,0 +1,289 @@ + /* + * 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. + * + */ + +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + +/* permit direct access to the libc calls (turn off config.h masking) */ +#define PCB_SAFE_FS + +#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" + +/* opendir, readdir */ +#include "compat_inc.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; +} + Index: tags/1.2.7/src/safe_fs.h =================================================================== --- tags/1.2.7/src/safe_fs.h (nonexistent) +++ tags/1.2.7/src/safe_fs.h (revision 13657) @@ -0,0 +1,64 @@ + /* + * 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. + * + */ + +/* 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); + +/* 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/1.2.7/src/search.c =================================================================== --- tags/1.2.7/src/search.c (nonexistent) +++ tags/1.2.7/src/search.c (revision 13657) @@ -0,0 +1,1711 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* 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" + +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_TYPE_LOCKED if we + * want to include locked object in the search and PCB_TYPE_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 SearchPinByLocation(unsigned long, unsigned long, pcb_element_t **, pcb_pin_t **, pcb_pin_t **); +static pcb_bool SearchPadByLocation(unsigned long, unsigned long, pcb_element_t **, pcb_pad_t **, pcb_pad_t **, pcb_bool); +static pcb_bool SearchViaByLocation(unsigned long, unsigned long, pcb_pin_t **, pcb_pin_t **, pcb_pin_t **); +static pcb_bool SearchElementNameByLocation(unsigned long, unsigned long, pcb_element_t **, pcb_text_t **, pcb_text_t **, pcb_bool); +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 SearchElementByLocation(unsigned long, unsigned long, pcb_element_t **, pcb_element_t **, pcb_element_t **, pcb_bool); +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) \ +do { \ + if ((req_flag != 0) && (!PCB_FLAG_TEST(req_flag, obj))) \ + return PCB_R_DIR_NOT_FOUND; \ + if (!(objst & PCB_TYPE_SUBC_PART) && (pcb_ ## locality ## obj_parent_subc(obj->parent_type, &obj->parent))) \ + return PCB_R_DIR_NOT_FOUND; \ + if (!(objst & PCB_TYPE_LOCKED) && (PCB_FLAG_TEST(objst & PCB_FLAG_LOCK, locked_obj))) \ + return PCB_R_DIR_NOT_FOUND; \ +} while(0) + +/* --------------------------------------------------------------------------- + * searches a via + */ +struct ans_info { + void **ptr1, **ptr2, **ptr3; + pcb_bool BackToo; + double area; + unsigned long objst, req_flag; +}; + +static pcb_r_dir_t pinorvia_callback(const pcb_box_t * box, void *cl) +{ + struct ans_info *i = (struct ans_info *) cl; + pcb_pin_t *pin = (pcb_pin_t *) box; + pcb_any_obj_t *ptr1 = pin->Element ? pin->Element : pin; + + TEST_OBJST(i->objst, i->req_flag, g, pin, ptr1); + + if (!pcb_is_point_in_pin(PosX, PosY, SearchRadius, pin)) + return PCB_R_DIR_NOT_FOUND; + *i->ptr1 = ptr1; + *i->ptr2 = *i->ptr3 = pin; + return PCB_R_DIR_CANCEL; /* found, stop searching */ +} + +static pcb_bool SearchViaByLocation(unsigned long objst, unsigned long req_flag, pcb_pin_t ** Via, pcb_pin_t ** Dummy1, pcb_pin_t ** Dummy2) +{ + struct ans_info info; + + /* search only if via-layer is visible */ + if (!PCB->ViaOn) + return pcb_false; + + info.ptr1 = (void **) Via; + info.ptr2 = (void **) Dummy1; + info.ptr3 = (void **) Dummy2; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(PCB->Data->via_tree, &SearchBox, NULL, pinorvia_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * 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; + + 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; + *i->ptr1 = *i->ptr2 = *i->ptr3 = ps; + 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) +{ + struct ans_info info; + + /* search only if via-layer is visible */ + if (!PCB->ViaOn) + return pcb_false; + + info.ptr1 = (void **)ps; + info.ptr2 = (void **)Dummy1; + info.ptr3 = (void **)Dummy2; + info.objst = objst; + info.req_flag = req_flag; + + 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 a pin + * starts with the newest element + */ +static pcb_bool SearchPinByLocation(unsigned long objst, unsigned long req_flag, pcb_element_t ** Element, pcb_pin_t ** Pin, pcb_pin_t ** Dummy) +{ + struct ans_info info; + + /* search only if pin-layer is visible */ + if (!PCB->PinOn) + return pcb_false; + info.ptr1 = (void **) Element; + info.ptr2 = (void **) Pin; + info.ptr3 = (void **) Dummy; + info.objst = objst; + info.req_flag = req_flag; + + if (pcb_r_search(PCB->Data->pin_tree, &SearchBox, NULL, pinorvia_callback, &info, NULL) != PCB_R_DIR_NOT_FOUND) + return pcb_true; + return pcb_false; +} + +static pcb_r_dir_t pad_callback(const pcb_box_t * b, void *cl) +{ + pcb_pad_t *pad = (pcb_pad_t *) b; + struct ans_info *i = (struct ans_info *) cl; + pcb_any_obj_t *ptr1 = pad->Element; + + TEST_OBJST(i->objst, i->req_flag, g, pad, ptr1); + + if (PCB_FRONT(pad) || i->BackToo) { + if (pcb_is_point_in_pad(PosX, PosY, SearchRadius, pad)) { + *i->ptr1 = ptr1; + *i->ptr2 = *i->ptr3 = pad; + return PCB_R_DIR_CANCEL; /* found */ + } + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches a pad + * starts with the newest element + */ +static pcb_bool SearchPadByLocation(unsigned long objst, unsigned long req_flag, pcb_element_t ** Element, pcb_pad_t ** Pad, pcb_pad_t ** Dummy, pcb_bool BackToo) +{ + struct ans_info info; + + /* search only if pin-layer is visible */ + if (!PCB->PinOn) + return (pcb_false); + info.ptr1 = (void **) Element; + info.ptr2 = (void **) Pad; + info.ptr3 = (void **) Dummy; + info.objst = objst; + info.req_flag = req_flag; + info.BackToo = (BackToo && PCB->InvisibleObjectsOn); + if (pcb_r_search(PCB->Data->pad_tree, &SearchBox, NULL, pad_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_pad(PosX, PosY, SearchRadius, (pcb_pad_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; /* 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_TYPE_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 name_callback(const pcb_box_t * box, void *cl) +{ + pcb_text_t *text = (pcb_text_t *) box; + struct ans_info *i = (struct ans_info *) cl; + pcb_element_t *element = (pcb_element_t *) text->Element; + double newarea; + + TEST_OBJST(i->objst, i->req_flag, l, text, text); + + if ((PCB_FRONT(element) || i->BackToo) && !PCB_FLAG_TEST(PCB_FLAG_HIDENAME, element) && PCB_POINT_IN_BOX(PosX, PosY, &text->BoundingBox)) { + /* use the text with the smallest bounding box */ + newarea = (text->BoundingBox.X2 - text->BoundingBox.X1) * (double) (text->BoundingBox.Y2 - text->BoundingBox.Y1); + if (newarea < i->area) { + i->area = newarea; + *i->ptr1 = element; + *i->ptr2 = *i->ptr3 = text; + } + return PCB_R_DIR_FOUND_CONTINUE; + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches the name of an element + */ +static pcb_bool +SearchElementNameByLocation(unsigned long objst, unsigned long req_flag, pcb_element_t ** Element, pcb_text_t ** Text, pcb_text_t ** Dummy, pcb_bool BackToo) +{ + struct ans_info info; + + /* package layer have to be switched on */ + if (pcb_silk_on(PCB)) { + info.ptr1 = (void **) Element; + info.ptr2 = (void **) Text; + info.ptr3 = (void **) Dummy; + 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->name_tree[PCB_ELEMNAME_IDX_VISIBLE()], &SearchBox, NULL, name_callback, &info, NULL)) + return pcb_true; + } + return (pcb_false); +} + +static pcb_r_dir_t element_callback(const pcb_box_t * box, void *cl) +{ + pcb_element_t *element = (pcb_element_t *) box; + struct ans_info *i = (struct ans_info *) cl; + double newarea; + + TEST_OBJST(i->objst, i->req_flag, g, element, element); + + if ((PCB_FRONT(element) || i->BackToo) && PCB_POINT_IN_BOX(PosX, PosY, &element->VBox) && pcb_element_silk_vis(element)) { + /* use the element with the smallest bounding box */ + newarea = (element->VBox.X2 - element->VBox.X1) * (double) (element->VBox.Y2 - element->VBox.Y1); + if (newarea < i->area) { + i->area = newarea; + *i->ptr1 = *i->ptr2 = *i->ptr3 = element; + return PCB_R_DIR_FOUND_CONTINUE; + } + } + return PCB_R_DIR_NOT_FOUND; +} + +/* --------------------------------------------------------------------------- + * searches an element + * if more than one element matches, the smallest one is taken + */ +static pcb_bool +SearchElementByLocation(unsigned long objst, unsigned long req_flag, pcb_element_t ** Element, pcb_element_t ** Dummy1, pcb_element_t ** Dummy2, pcb_bool BackToo) +{ + struct ans_info info; + + /* Both package layers have to be switched on */ + if (pcb_silk_on(PCB) && PCB->PinOn) { + info.ptr1 = (void **) Element; + 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->element_tree, &SearchBox, NULL, element_callback, &info, NULL)) + 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; + + TEST_OBJST(i->objst, i->req_flag, g, subc, subc); + + if ((PCB_FRONT(subc) || i->BackToo) && PCB_POINT_IN_BOX(PosX, PosY, &subc->BoundingBox)) { + /* use the element 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; +} + +pcb_bool pcb_is_point_in_pin(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_pin_t *pin) +{ + pcb_coord_t t = PIN_SIZE(pin) / 2; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) { + pcb_box_t b; + + b.X1 = pin->X - t; + b.X2 = pin->X + t; + b.Y1 = pin->Y - t; + b.Y2 = pin->Y + t; + if (pcb_is_point_in_box(X, Y, &b, Radius)) + return pcb_true; + } + else if (pcb_distance(pin->X, pin->Y, X, Y) <= Radius + t) + 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); +} + +/* --------------------------------------------------------------------------- + * checks if a line intersects with a PV + * + * let the point be (X,Y) and the line (X1,Y1)(X2,Y2) + * the length of the line is + * + * L = ((X2-X1)^2 + (Y2-Y1)^2)^0.5 + * + * let Q be the point of perpendicular projection of (X,Y) onto the line + * + * QX = X1 + D1*(X2-X1) / L + * QY = Y1 + D1*(Y2-Y1) / L + * + * with (from vector geometry) + * + * (Y1-Y)(Y1-Y2)+(X1-X)(X1-X2) + * D1 = --------------------------- + * L + * + * D1 < 0 Q is on backward extension of the line + * D1 > L Q is on forward extension of the line + * else Q is on the line + * + * the signed distance from (X,Y) to Q is + * + * (Y2-Y1)(X-X1)-(X2-X1)(Y-Y1) + * D2 = ---------------------------- + * L + * + * Finally, D1 and D2 are orthogonal, so we can sum them easily + * by Pythagorean theorem. + */ + +double pcb_point_line_dist2(pcb_coord_t X, pcb_coord_t Y, pcb_line_t *Line) +{ + double D1, D2, L; + + /* Get length of segment */ + L = pcb_distance2(Line->Point1.X, Line->Point1.Y, Line->Point2.X, Line->Point2.Y); + if (L < 0.01) + return pcb_distance2(X, Y, Line->Point1.X, Line->Point1.Y); + + /* Get distance from (X1, Y1) to Q (on the line) */ + D1 = ((double) (Y - Line->Point1.Y) * (Line->Point2.Y - Line->Point1.Y) + + (double) (X - Line->Point1.X) * (Line->Point2.X - Line->Point1.X)) / L; + /* Translate this into distance to Q from segment */ + if (D1 < 0) + D1 = -D1; + else if (D1 > L) + D1 -= L; + else + D1 = 0; + /* Get distance from (X, Y) to Q */ + D2 = ((double) (X - Line->Point1.X) * (Line->Point2.Y - Line->Point1.Y) + - (double) (Y - Line->Point1.Y) * (Line->Point2.X - Line->Point1.X)) / L; + + /* Total distance is then the Pythagorean sum of these */ + return D1 * D1 + D2 * D2; +} + +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); +} + +/* 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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_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_intersect_line_arc(&line, Arc)) + return (pcb_true); + + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * Check if a circle of Radius with center at (X, Y) intersects a Pad. + * Written to enable arbitrary pad directions; for rounded pads, too. + */ +pcb_bool pcb_is_point_in_pad(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_pad_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 = *(pcb_any_line_t *) 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->Width * 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->Width * 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 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; +#undef angle_in_range +} + +/* --------------------------------------------------------------------------- + * 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_TYPE_NONE 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, pin, via, line, text, elementname, polygon, element + * + * Note that if Type includes PCB_TYPE_LOCKED, then the search includes + * locked items. Otherwise, locked items are ignored. + + * Note that if Type includes PCB_TYPE_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_TYPE_NONE; + int objst = Type & (PCB_TYPE_LOCKED | PCB_TYPE_SUBC_PART); + + /* 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.lock_names) { + Type &= ~(PCB_TYPE_ELEMENT_NAME | PCB_TYPE_TEXT); + } + if (conf_core.editor.hide_names) { + Type &= ~PCB_TYPE_ELEMENT_NAME; + } + if (conf_core.editor.only_names) { + Type &= (PCB_TYPE_ELEMENT_NAME | PCB_TYPE_TEXT); + } + if (conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly) { + Type &= ~PCB_TYPE_POLY; + } + + if (Type & PCB_TYPE_RATLINE && PCB->RatOn && + SearchRatLineByLocation(objst, req_flag, (pcb_rat_t **) Result1, (pcb_rat_t **) Result2, (pcb_rat_t **) Result3)) + return (PCB_TYPE_RATLINE); + + if (Type & PCB_TYPE_VIA && SearchViaByLocation(objst, req_flag, (pcb_pin_t **) Result1, (pcb_pin_t **) Result2, (pcb_pin_t **) Result3)) + return (PCB_TYPE_VIA); + + if (Type & PCB_TYPE_PSTK && SearchPadstackByLocation(objst, req_flag, (pcb_pstk_t **) Result1, (pcb_pstk_t **) Result2, (pcb_pstk_t **) Result3)) + return (PCB_TYPE_PSTK); + + if (Type & PCB_TYPE_PIN && SearchPinByLocation(objst, req_flag, (pcb_element_t **) pr1, (pcb_pin_t **) pr2, (pcb_pin_t **) pr3)) + HigherAvail = PCB_TYPE_PIN; + + if (!HigherAvail && Type & PCB_TYPE_PAD && + SearchPadByLocation(objst, req_flag, (pcb_element_t **) pr1, (pcb_pad_t **) pr2, (pcb_pad_t **) pr3, pcb_false)) + HigherAvail = PCB_TYPE_PAD; + + if (!HigherAvail && Type & PCB_TYPE_ELEMENT_NAME && + SearchElementNameByLocation(objst, req_flag, (pcb_element_t **) pr1, (pcb_text_t **) pr2, (pcb_text_t **) pr3, pcb_false)) { + pcb_box_t *box = &((pcb_text_t *) r2)->BoundingBox; + HigherBound = (double) (box->X2 - box->X1) * (double) (box->Y2 - box->Y1); + HigherAvail = PCB_TYPE_ELEMENT_NAME; + } + + if (!HigherAvail && Type & PCB_TYPE_ELEMENT && + SearchElementByLocation(objst, req_flag, (pcb_element_t **) pr1, (pcb_element_t **) pr2, (pcb_element_t **) pr3, pcb_false)) { + pcb_box_t *box = &((pcb_element_t *) r1)->BoundingBox; + HigherBound = (double) (box->X2 - box->X1) * (double) (box->Y2 - box->Y1); + HigherAvail = PCB_TYPE_ELEMENT; + } + + if (!HigherAvail && Type & PCB_TYPE_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_TYPE_SUBC; + } + + for (i = -1; i < pcb_max_layer + 1; i++) { + 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) + SearchLayer = &PCB->Data->SILKLAYER; + else if (i < pcb_max_layer) + SearchLayer = LAYER_ON_STACK(i); + + else { + SearchLayer = &PCB->Data->BACKSILKLAYER; + if (!PCB->InvisibleObjectsOn) + continue; + } + if (SearchLayer->meta.real.vis) { + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && + Type & PCB_TYPE_POLY_POINT && + SearchPointByLocation(Type, objst, req_flag, (pcb_layer_t **) Result1, (pcb_poly_t **) Result2, (pcb_point_t **) Result3)) + return (PCB_TYPE_POLY_POINT); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && + Type & PCB_TYPE_LINE_POINT && + SearchLinePointByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_line_t **) Result2, (pcb_point_t **) Result3)) + return (PCB_TYPE_LINE_POINT); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && + Type & PCB_TYPE_ARC_POINT && + SearchArcPointByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_arc_t **) Result2, (int **) Result3)) + return (PCB_TYPE_ARC_POINT); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && Type & PCB_TYPE_LINE + && SearchLineByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_line_t **) Result2, (pcb_line_t **) Result3)) + return (PCB_TYPE_LINE); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && Type & PCB_TYPE_ARC && + SearchArcByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_arc_t **) Result2, (pcb_arc_t **) Result3)) + return (PCB_TYPE_ARC); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && Type & PCB_TYPE_TEXT + && SearchTextByLocation(objst, req_flag, (pcb_layer_t **) Result1, (pcb_text_t **) Result2, (pcb_text_t **) Result3)) + return (PCB_TYPE_TEXT); + + if (Type & PCB_TYPE_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) + break; + else + return (PCB_TYPE_POLY); + } + else + return (PCB_TYPE_POLY); + } + } + } + /* return any previously found objects */ + if (HigherAvail & PCB_TYPE_PIN) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return (PCB_TYPE_PIN); + } + + if (HigherAvail & PCB_TYPE_PAD) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return (PCB_TYPE_PAD); + } + + if (HigherAvail & PCB_TYPE_ELEMENT_NAME) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return (PCB_TYPE_ELEMENT_NAME); + } + + if (HigherAvail & PCB_TYPE_ELEMENT) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return (PCB_TYPE_ELEMENT); + } + + if (HigherAvail & PCB_TYPE_SUBC) { + *Result1 = r1; + *Result2 = r2; + *Result3 = r3; + return (PCB_TYPE_SUBC); + } + + /* search the 'invisible objects' last */ + if (!PCB->InvisibleObjectsOn) + return (PCB_TYPE_NONE); + + if (Type & PCB_TYPE_PAD && + SearchPadByLocation(objst, req_flag, (pcb_element_t **) Result1, (pcb_pad_t **) Result2, (pcb_pad_t **) Result3, pcb_true)) + return (PCB_TYPE_PAD); + + if (Type & PCB_TYPE_ELEMENT_NAME && + SearchElementNameByLocation(objst, req_flag, (pcb_element_t **) Result1, (pcb_text_t **) Result2, (pcb_text_t **) Result3, pcb_true)) + return (PCB_TYPE_ELEMENT_NAME); + + if (Type & PCB_TYPE_ELEMENT && + SearchElementByLocation(objst, req_flag, (pcb_element_t **) Result1, (pcb_element_t **) Result2, (pcb_element_t **) Result3, pcb_true)) + return (PCB_TYPE_ELEMENT); + + if (Type & PCB_TYPE_SUBC && PCB->SubcOn && + SearchSubcByLocation(objst, req_flag, (pcb_subc_t **) Result1, (pcb_subc_t **) Result2, (pcb_subc_t **) Result3, pcb_true)) + return (PCB_TYPE_SUBC); + + return (PCB_TYPE_NONE); +} + +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 = pcb_search_obj_by_location_(Type, Result1, Result2, Result3, X, Y, Radius, 0); + if ((res != PCB_TYPE_NONE) && (res != PCB_TYPE_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_TYPE_SUBC; + Type |= PCB_TYPE_SUBC_PART; + fres = pcb_search_obj_by_location_(Type, &fr1, &fr2, &fr3, X, Y, Radius, PCB_FLAG_FLOATER); + if (fres != PCB_TYPE_NONE) { + *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_TYPE_NONE if no objects has been found. + */ +static int pcb_search_obj_by_id_(pcb_data_t *Base, void **Result1, void **Result2, void **Result3, int ID, int type) +{ + if (type == PCB_TYPE_LINE || type == PCB_TYPE_LINE_POINT) { + PCB_LINE_ALL_LOOP(Base); + { + if (line->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) line; + return (PCB_TYPE_LINE); + } + if (line->Point1.ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point1; + return (PCB_TYPE_LINE_POINT); + } + if (line->Point2.ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point2; + return (PCB_TYPE_LINE_POINT); + } + } + PCB_ENDALL_LOOP; + } + if (type == PCB_TYPE_ARC || type == PCB_TYPE_ARC_POINT) { + PCB_ARC_ALL_LOOP(Base); + { + if (arc->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) arc; + return (PCB_TYPE_ARC); + } + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_TYPE_TEXT) { + PCB_TEXT_ALL_LOOP(Base); + { + if (text->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) text; + return (PCB_TYPE_TEXT); + } + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_TYPE_POLY || type == PCB_TYPE_POLY_POINT) { + PCB_POLY_ALL_LOOP(Base); + { + if (polygon->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) polygon; + return (PCB_TYPE_POLY); + } + if (type == PCB_TYPE_POLY_POINT) + PCB_POLY_POINT_LOOP(polygon); + { + if (point->ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) polygon; + *Result3 = (void *) point; + return (PCB_TYPE_POLY_POINT); + } + } + PCB_END_LOOP; + } + PCB_ENDALL_LOOP; + } + + if (type == PCB_TYPE_VIA) { + PCB_VIA_LOOP(Base); + { + if (via->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *) via; + return (PCB_TYPE_VIA); + } + } + PCB_END_LOOP; + } + + if (type == PCB_TYPE_PSTK) { + PCB_PADSTACK_LOOP(Base); + { + if (padstack->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *)padstack; + return PCB_TYPE_PSTK; + } + } + PCB_END_LOOP; + } + + if (type == PCB_TYPE_RATLINE || type == PCB_TYPE_LINE_POINT) { + PCB_RAT_LOOP(Base); + { + if (line->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *) line; + return (PCB_TYPE_RATLINE); + } + if (line->Point1.ID == ID) { + *Result1 = (void *) NULL; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point1; + return (PCB_TYPE_LINE_POINT); + } + if (line->Point2.ID == ID) { + *Result1 = (void *) NULL; + *Result2 = (void *) line; + *Result3 = (void *) &line->Point2; + return (PCB_TYPE_LINE_POINT); + } + } + PCB_END_LOOP; + } + +#warning subc TODO: once elements are gone, rewrite these to search the rtree instead of recursion + PCB_SUBC_LOOP(Base); + { + int res; + if (type == PCB_TYPE_SUBC) { + if (subc->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *)subc; + return PCB_TYPE_SUBC; + } + } + + res = pcb_search_obj_by_id_(subc->data, Result1, Result2, Result3, ID, type); + if (res != PCB_TYPE_NONE) + return res; + } + PCB_END_LOOP; + + if (type == PCB_TYPE_ELEMENT || type == PCB_TYPE_PAD || type == PCB_TYPE_PIN + || type == PCB_TYPE_ELEMENT_LINE || type == PCB_TYPE_ELEMENT_NAME || type == PCB_TYPE_ELEMENT_ARC) + /* check pins and elementnames too */ + PCB_ELEMENT_LOOP(Base); + { + if (element->ID == ID) { + *Result1 = *Result2 = *Result3 = (void *) element; + return (PCB_TYPE_ELEMENT); + } + if (type == PCB_TYPE_ELEMENT_LINE) + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + if (line->ID == ID) { + *Result1 = (void *) element; + *Result2 = *Result3 = (void *) line; + return (PCB_TYPE_ELEMENT_LINE); + } + } + PCB_END_LOOP; + if (type == PCB_TYPE_ELEMENT_ARC) + PCB_ARC_LOOP(element); + { + if (arc->ID == ID) { + *Result1 = (void *) element; + *Result2 = *Result3 = (void *) arc; + return (PCB_TYPE_ELEMENT_ARC); + } + } + PCB_END_LOOP; + if (type == PCB_TYPE_ELEMENT_NAME) + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + if (text->ID == ID) { + *Result1 = (void *) element; + *Result2 = *Result3 = (void *) text; + return (PCB_TYPE_ELEMENT_NAME); + } + } + PCB_END_LOOP; + if (type == PCB_TYPE_PIN) + PCB_PIN_LOOP(element); + { + if (pin->ID == ID) { + *Result1 = (void *) element; + *Result2 = *Result3 = (void *) pin; + return (PCB_TYPE_PIN); + } + } + PCB_END_LOOP; + if (type == PCB_TYPE_PAD) + PCB_PAD_LOOP(element); + { + if (pad->ID == ID) { + *Result1 = (void *) element; + *Result2 = *Result3 = (void *) pad; + return (PCB_TYPE_PAD); + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + return (PCB_TYPE_NONE); +} + +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_TYPE_NONE) + pcb_message(PCB_MSG_ERROR, "hace: Internal error, search for ID %d failed\n", ID); + return res; +} + + +/* --------------------------------------------------------------------------- + * searches for an element by its refdes. + * Return the element or NULL if not found + */ +pcb_element_t *pcb_search_elem_by_name(pcb_data_t *Base, const char *Name) +{ + pcb_element_t *result = NULL; + + PCB_ELEMENT_LOOP(Base); + { + if (element->Name[1].TextString && PCB_NSTRCMP(element->Name[1].TextString, Name) == 0) { + result = element; + return (result); + } + } + PCB_END_LOOP; + return result; +} + +/* --------------------------------------------------------------------------- + * 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; +} Index: tags/1.2.7/src/search.h =================================================================== --- tags/1.2.7/src/search.h (nonexistent) +++ tags/1.2.7/src/search.h (revision 13657) @@ -0,0 +1,182 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* Search object by location routines */ + +#ifndef PCB_SEARCH_H +#define PCB_SEARCH_H + +#include "global_typedefs.h" +#include "rats.h" +#include "misc_util.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_line_end(pcb_coord_t X, pcb_coord_t Y, pcb_rat_t *Line); +pcb_bool pcb_is_point_in_pin(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_pin_t *pin); +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_pad(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_pad_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); + +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); +pcb_element_t *pcb_search_elem_by_name(pcb_data_t *Base, const char *Name); + +#endif Index: tags/1.2.7/src/select.c =================================================================== --- tags/1.2.7/src/select.c (nonexistent) +++ tags/1.2.7/src/select.c (revision 13657) @@ -0,0 +1,887 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + + +/* select routines + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.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 "compat_nls.h" + +#include "obj_elem_draw.h" +#include "obj_pad_draw.h" +#include "obj_arc_draw.h" +#include "obj_pinvia_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 + +void pcb_select_element(pcb_board_t *pcb, pcb_element_t *element, pcb_change_flag_t how, int redraw) +{ + /* select all pins and names of the element */ + PCB_PIN_LOOP(element); + { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, pad); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, text); + } + PCB_END_LOOP; + pcb_undo_add_obj_to_flag(element); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, element); + + if (redraw) { + if (pcb_silk_on(pcb) && ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) != 0) == PCB_SWAP_IDENT || pcb->InvisibleObjectsOn)) + if (pcb_silk_on(pcb)) { + pcb_elem_name_invalidate_draw(element); + pcb_elem_package_invalidate_draw(element); + } + if (pcb->PinOn) + pcb_elem_pp_invalidate_draw(element); + } +} + +void pcb_select_element_name(pcb_element_t *element, pcb_change_flag_t how, int redraw) +{ + /* select all names of the element */ + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, text); + } + PCB_END_LOOP; + + if (redraw) + pcb_elem_name_invalidate_draw(element); +} + + +/* --------------------------------------------------------------------------- + * 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, &ptr1, &ptr2, &ptr3); + if (type == PCB_TYPE_NONE || PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) + return (pcb_false); + switch (type) { + case PCB_TYPE_VIA: + pcb_undo_add_obj_to_flag(ptr1); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr1); + pcb_via_invalidate_draw((pcb_pin_t *) ptr1); + break; + + case PCB_TYPE_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_TYPE_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_TYPE_RATLINE: + { + 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_TYPE_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_TYPE_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_TYPE_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_TYPE_PIN: + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr2); + pcb_pin_invalidate_draw((pcb_pin_t *) ptr2); + break; + + case PCB_TYPE_PAD: + pcb_undo_add_obj_to_flag(ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pad_t *) ptr2); + pcb_pad_invalidate_draw((pcb_pad_t *) ptr2); + break; + + case PCB_TYPE_ELEMENT_NAME: + pcb_select_element_name((pcb_element_t *) ptr1, PCB_CHGFLG_TOGGLE, 1); + break; + + case PCB_TYPE_ELEMENT: + pcb_select_element(pcb, (pcb_element_t *) ptr1, PCB_CHGFLG_TOGGLE, 1); + break; + + case PCB_TYPE_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. + */ +#warning cleanup TODO: 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_TYPE_RATLINE, 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_TYPE_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_TYPE_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_TYPE_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_TYPE_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; + } + + /* elements */ + PCB_ELEMENT_LOOP(pcb->Data); + { + { + pcb_bool gotElement = pcb_false; + if ((pcb_silk_on(pcb) || !Flag) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, element) + && ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) != 0) == PCB_SWAP_IDENT || pcb->InvisibleObjectsOn)) { + if (PCB_BOX_NEAR_BOX(&PCB_ELEM_TEXT_VISIBLE(PCB, element).BoundingBox, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, &PCB_ELEM_TEXT_VISIBLE(PCB, element)) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element)) != Flag) { + /* select all names of element */ + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + append(PCB_TYPE_ELEMENT_NAME, element, text); + } + PCB_END_LOOP; + if (pcb_silk_on(pcb)) + pcb_elem_name_invalidate_draw(element); + } + if ((pcb->PinOn || !Flag) && PCB_ELEMENT_NEAR_BOX(element, Box)) + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element) != Flag) { + append(PCB_TYPE_ELEMENT, element, element); + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin) != Flag) { + append(PCB_TYPE_PIN, element, pin); + if (pcb->PinOn) + pcb_pin_invalidate_draw(pin); + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad) != Flag) { + append(PCB_TYPE_PAD, element, pad); + if (pcb->PinOn) + pcb_pad_invalidate_draw(pad); + } + } + PCB_END_LOOP; + if (pcb->PinOn) + pcb_elem_invalidate_draw(element); + gotElement = pcb_true; + } + } + if ((pcb->PinOn || !Flag) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, element) && !gotElement) { + PCB_PIN_LOOP(element); + { + if ((PCB_VIA_OR_PIN_NEAR_BOX(pin, Box) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin) != Flag)) { + append(PCB_TYPE_PIN, element, pin); + if (pcb->PinOn) + pcb_pin_invalidate_draw(pin); + } + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (PCB_PAD_NEAR_BOX(pad, Box) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad) != Flag + && (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) == PCB_SWAP_IDENT || pcb->InvisibleObjectsOn || !Flag)) { + append(PCB_TYPE_PAD, element, pad); + if (pcb->PinOn) + pcb_pad_invalidate_draw(pad); + } + } + PCB_END_LOOP; + } + } + } + PCB_END_LOOP; + + /* end with vias */ + if (pcb->ViaOn || !Flag) { + PCB_VIA_LOOP(pcb->Data); + { + if (PCB_VIA_OR_PIN_NEAR_BOX(via, Box) + && !PCB_FLAG_TEST(PCB_FLAG_LOCK, via) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, via) != Flag) { + append(PCB_TYPE_VIA, via, via); + if (pcb->ViaOn) + pcb_via_invalidate_draw(via); + } + } + PCB_END_LOOP; + + 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_TYPE_PSTK, padstack, padstack); + if (pcb->ViaOn) + 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_ETEXT: + 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_PAD: return PCB_PAD_NEAR_BOX((pcb_pad_t *)obj, box); + case PCB_OBJ_PSTK: return pcb_pstk_near_box((pcb_pstk_t *)obj, box, NULL); + case PCB_OBJ_PIN: + case PCB_OBJ_VIA: return PCB_VIA_OR_PIN_NEAR_BOX((pcb_pin_t *)obj, box); + case PCB_OBJ_ELEMENT: return PCB_ELEMENT_NEAR_BOX((pcb_element_t *)obj, box); + 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; +} 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 (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; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, obj) == pcb_true) + 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_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) +{ + select_ctx_t ctx; + + fix_box_dir(Box, 0); + + ctx.box = *Box; + ctx.flag = flag; + + fix_box_dir(Box, 1); + + return pcb_data_r_search(pcb->Data, PCB_OBJ_ANY, Box, NULL, pcb_select_block_cb, &ctx, NULL) == 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 elements cannot be selected by this routine + */ +pcb_bool pcb_select_connection(pcb_board_t *pcb, pcb_bool Flag) +{ + pcb_bool changed = pcb_false; + + if (pcb->RatOn) + PCB_RAT_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, line)) { + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, line); + pcb_rat_invalidate_draw(line); + changed = pcb_true; + } + } + PCB_END_LOOP; + + PCB_LINE_VISIBLE_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, line) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, line)) { + pcb_undo_add_obj_to_flag(line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, line); + pcb_line_invalidate_draw(layer, line); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_ARC_VISIBLE_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, arc) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, arc)) { + pcb_undo_add_obj_to_flag(arc); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, arc); + pcb_arc_invalidate_draw(layer, arc); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_POLY_VISIBLE_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, polygon) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, polygon)) { + pcb_undo_add_obj_to_flag(polygon); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, polygon); + pcb_poly_invalidate_draw(layer, polygon); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + + if (pcb->PinOn && pcb_silk_on(pcb)) { + PCB_PIN_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) && PCB_FLAG_TEST(PCB_FLAG_FOUND, pin)) { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + pcb_pin_invalidate_draw(pin); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_PAD_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) && PCB_FLAG_TEST(PCB_FLAG_FOUND, pad)) { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + pcb_pad_invalidate_draw(pad); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + } + + if (pcb->ViaOn) + PCB_VIA_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, via) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, via)) { + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, via); + pcb_via_invalidate_draw(via); + changed = pcb_true; + } + } + PCB_END_LOOP; + return (changed); +} + +/* --------------------------------------------------------------------------- + * 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 element 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; +} + +pcb_bool pcb_select_object_by_name(pcb_board_t *pcb, int Type, const char *name_pattern, pcb_bool Flag, pcb_search_method_t method) +{ + pcb_bool changed = pcb_false; + const char **pat = NULL; + char *pattern_copy = NULL; + re_sei_t *regex; + + if (method == PCB_SM_REGEX) { + /* compile the regular expression */ + regex = re_sei_comp(name_pattern); + if (re_sei_errno(regex) != 0) { + pcb_message(PCB_MSG_ERROR, _("regexp error: %s\n"), re_error_str(re_sei_errno(regex))); + re_sei_free(regex); + return (pcb_false); + } + } + else { + char *s, *next; + int n, w; + + /* We're going to mess with the delimiters. Create a copy. */ + pattern_copy = pcb_strdup(name_pattern); + + /* count the number of patterns */ + for (s = pattern_copy, w = 0; *s != '\0'; s++) { + if (*s == '|') + w++; + } + + pat = malloc((w + 2) * sizeof(char *)); /* make room for the NULL too */ + for (s = pattern_copy, n = 0; s != NULL; s = next) { + char *end; +/*fprintf(stderr, "S: '%s'\n", s, next);*/ + while (isspace(*s)) + s++; + next = strchr(s, '|'); + if (next != NULL) { + *next = '\0'; + next++; + } + end = s + strlen(s) - 1; + while ((end >= s) && (isspace(*end))) { + *end = '\0'; + end--; + } + if (*s != '\0') { + pat[n] = s; + n++; + } + } + pat[n] = NULL; + } + + /* loop over all visible objects with names */ + if (Type & PCB_TYPE_TEXT) + PCB_TEXT_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, text) + && pcb_text_is_visible(PCB, layer, text) + && text->TextString && REGEXEC(text->TextString) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) != Flag) { + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, text); + pcb_text_invalidate_draw(layer, text); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + + if (pcb_silk_on(pcb) && (Type & PCB_TYPE_ELEMENT)) + PCB_ELEMENT_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) + && ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) != 0) == PCB_SWAP_IDENT || pcb->InvisibleObjectsOn) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, element) != Flag) { + const char* name = PCB_ELEM_NAME_VISIBLE(PCB, element); + if (name && REGEXEC(name)) { + pcb_undo_add_obj_to_flag(element); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, element); + PCB_PIN_LOOP(element); + { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_undo_add_obj_to_flag(text); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, text); + } + PCB_END_LOOP; + pcb_elem_name_invalidate_draw(element); + pcb_elem_invalidate_draw(element); + changed = pcb_true; + } + } + } + PCB_END_LOOP; + if (pcb->PinOn && (Type & PCB_TYPE_PIN)) + PCB_PIN_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) + && pin->Name && REGEXEC(pin->Name) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin) != Flag) { + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + pcb_pin_invalidate_draw(pin); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (pcb->PinOn && (Type & PCB_TYPE_PAD)) + PCB_PAD_ALL_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) + && ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) != 0) == PCB_SWAP_IDENT || pcb->InvisibleObjectsOn) + && PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad) != Flag) + if (pad->Name && REGEXEC(pad->Name)) { + pcb_undo_add_obj_to_flag(pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + pcb_pad_invalidate_draw(pad); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (pcb->ViaOn && (Type & PCB_TYPE_VIA)) + PCB_VIA_LOOP(pcb->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, via) + && via->Name && REGEXEC(via->Name) && PCB_FLAG_TEST(PCB_FLAG_SELECTED, via) != Flag) { + pcb_undo_add_obj_to_flag(via); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, via); + pcb_via_invalidate_draw(via); + changed = pcb_true; + } + } + PCB_END_LOOP; + if (Type & PCB_TYPE_NET) { + pcb_conn_lookup_init(); + changed = pcb_reset_conns(pcb_true) || changed; + + PCB_MENU_LOOP(&(pcb->NetlistLib[PCB_NETLIST_EDITED])); + { + pcb_cardinal_t i; + pcb_lib_entry_t *entry; + pcb_connection_t conn; + + /* Name[0] and Name[1] are special purpose, not the actual name */ + if (menu->Name && menu->Name[0] != '\0' && menu->Name[1] != '\0' && REGEXEC(menu->Name + 2)) { + for (i = menu->EntryN, entry = menu->Entry; i; i--, entry++) + if (pcb_rat_seek_pad(entry, &conn, pcb_false)) + pcb_rat_find_hook(conn.obj, pcb_true, pcb_true); + } + } + PCB_END_LOOP; + + changed = pcb_select_connection(pcb, Flag) || changed; + changed = pcb_reset_conns(pcb_false) || changed; + pcb_conn_lookup_uninit(); + } + + if (method == PCB_SM_REGEX) + re_sei_free(regex); + + if (changed) { + pcb_undo_inc_serial(); + pcb_draw(); + } + if (pat != NULL) + free(pat); + if (pattern_copy != NULL) + free(pattern_copy); + return (changed); +} Index: tags/1.2.7/src/select.h =================================================================== --- tags/1.2.7/src/select.h (nonexistent) +++ tags/1.2.7/src/select.h (revision 13657) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_SELECT_H +#define PCB_SELECT_H + +#include "config.h" +#include "operation.h" + +#define PCB_SELECT_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_POLY | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | \ + PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_PSTK | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_RATLINE | PCB_TYPE_ARC) + +pcb_bool pcb_select_object(pcb_board_t *pcb); +pcb_bool pcb_select_block(pcb_board_t *pcb, pcb_box_t *, pcb_bool); +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); + + +typedef enum { + PCB_SM_REGEX = 0, + PCB_SM_LIST = 1 +} pcb_search_method_t; + +pcb_bool pcb_select_object_by_name(pcb_board_t *pcb, int, const char *, pcb_bool, pcb_search_method_t); + +/* New API */ + +/* Change the selection of an element or element name (these have side effects) */ +void pcb_select_element(pcb_board_t *pcb, pcb_element_t *element, pcb_change_flag_t how, int redraw); +void pcb_select_element_name(pcb_element_t *element, pcb_change_flag_t how, int redraw); + +#endif Index: tags/1.2.7/src/select_act.c =================================================================== --- tags/1.2.7/src/select_act.c (nonexistent) +++ tags/1.2.7/src/select_act.c (revision 13657) @@ -0,0 +1,407 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.h" +#include "error.h" +#include "undo.h" +#include "funchash_core.h" + +#include "tool.h" +#include "select.h" +#include "draw.h" +#include "remove.h" +#include "copy.h" +#include "hid_attrib.h" +#include "compat_misc.h" +#include "compat_nls.h" + +/* --------------------------------------------------------------------------- */ +/* Ask the user for a search pattern */ +static char *gui_get_pat(pcb_search_method_t * method) +{ + const char *methods[] = { "regexp", "list of names", NULL }; + pcb_hid_attribute_t attrs[2]; +#define nattr sizeof(attrs)/sizeof(attrs[0]) + static pcb_hid_attr_val_t results[nattr] = { 0 }; + + memset(attrs, 0, sizeof(attrs)); + + attrs[0].name = "Pattern"; + attrs[0].help_text = "Name/refdes pattern"; + attrs[0].type = PCB_HATT_STRING; + attrs[0].default_val.str_value = results[0].str_value; + + attrs[1].name = "Method"; + attrs[1].help_text = "method of search: either regular expression or a list of full names separated by |"; + attrs[1].type = PCB_HATT_ENUM; + attrs[1].enumerations = methods; + attrs[1].default_val.int_value = results[1].int_value; + + pcb_gui->attribute_dialog(attrs, nattr, results, "Find element", "Find element by name", NULL); + + *method = results[1].int_value; + if (results[0].str_value == NULL) + return NULL; + return pcb_strdup(results[0].str_value); +#undef nattr +} + + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Select[] = + "Select(Object|ToggleObject)\n" + "Select(All|Block|Connection)\n" + "Select(ElementByName|ObjectByName|PadByName|PinByName)\n" + "Select(ElementByName|ObjectByName|PadByName|PinByName, Name)\n" + "Select(TextByName|ViaByName|NetByName)\n" "Select(TextByName|ViaByName|NetByName, Name)\n" "Select(Convert)"; + +static const char pcb_acth_Select[] = "Toggles or sets the selection."; + +/* %start-doc actions Select + +@table @code + +@item ElementByName +@item ObjectByName +@item PadByName +@item PinByName +@item TextByName +@item ViaByName +@item NetByName + +These all rely on having a regular expression parser built into +@code{pcb}. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are selected. + +@item Object +@item ToggleObject +Selects the object under the cursor. + +@item Block +Selects all objects in a rectangle indicated by the cursor. + +@item All +Selects all objects on the board. + +@item Connection +Selects all connections with the ``found'' flag set. + +@item Convert +Converts the selected objects to an element. This uses the highest +numbered paste buffer. + +@end table + +%end-doc */ + +static int pcb_act_Select(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + int type; + + switch (pcb_funchash_get(function, NULL)) { /* select objects by their names */ + case F_ElementByName: + type = PCB_TYPE_ELEMENT; + goto commonByName; + case F_ObjectByName: + type = PCB_TYPEMASK_ALL; + goto commonByName; + case F_PadByName: + type = PCB_TYPE_PAD; + goto commonByName; + case F_PinByName: + type = PCB_TYPE_PIN; + goto commonByName; + case F_TextByName: + type = PCB_TYPE_TEXT; + goto commonByName; + case F_ViaByName: + type = PCB_TYPE_VIA; + goto commonByName; + case F_NetByName: + type = PCB_TYPE_NET; + goto commonByName; + + commonByName: + { + const char *pattern = PCB_ACTION_ARG(1); + pcb_search_method_t method = PCB_SM_REGEX; + + if (pattern || (pattern = gui_get_pat(&method)) != NULL) { + if (pcb_select_object_by_name(PCB, type, pattern, pcb_true, method)) + pcb_board_set_changed_flag(pcb_true); + if (PCB_ACTION_ARG(1) == NULL) + free((char*)pattern); + } + break; + } + + /* 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_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_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: + { + 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_gui->get_coords(_("Select the Element's Mark Location"), &x, &y); + 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_element_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; + + 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_gui->get_coords(_("Select the Subcircuit's Origin (mark) Location"), &x, &y); + 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_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; + } + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Unselect[] = + "Unselect(All|Block|Connection)\n" + "Unselect(ElementByName|ObjectByName|PadByName|PinByName)\n" + "Unselect(ElementByName|ObjectByName|PadByName|PinByName, Name)\n" + "Unselect(TextByName|ViaByName)\n" "Unselect(TextByName|ViaByName, Name)\n"; + +static const char pcb_acth_Unselect[] = "Unselects the object at the pointer location or the specified objects."; + +/* %start-doc actions Unselect + +@table @code + +@item All +Unselect all objects. + +@item Block +Unselect all objects in a rectangle given by the cursor. + +@item Connection +Unselect all connections with the ``found'' flag set. + +@item ElementByName +@item ObjectByName +@item PadByName +@item PinByName +@item TextByName +@item ViaByName + +These all rely on having a regular expression parser built into +@code{pcb}. If the name is not specified then the user is prompted +for a pattern, and all objects that match the pattern and are of the +type specified are unselected. + + +@end table + +%end-doc */ + +static int pcb_act_Unselect(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + if (function) { + int type; + switch (pcb_funchash_get(function, NULL)) { + /* select objects by their names */ + case F_ElementByName: + type = PCB_TYPE_ELEMENT; + goto commonByName; + case F_ObjectByName: + type = PCB_TYPEMASK_ALL; + goto commonByName; + case F_PadByName: + type = PCB_TYPE_PAD; + goto commonByName; + case F_PinByName: + type = PCB_TYPE_PIN; + goto commonByName; + case F_TextByName: + type = PCB_TYPE_TEXT; + goto commonByName; + case F_ViaByName: + type = PCB_TYPE_VIA; + goto commonByName; + case F_NetByName: + type = PCB_TYPE_NET; + goto commonByName; + + commonByName: + { + const char *pattern = PCB_ACTION_ARG(1); + pcb_search_method_t method = PCB_SM_REGEX; + + if (pattern || (pattern = gui_get_pat(&method)) != NULL) { + if (pcb_select_object_by_name(PCB, type, pattern, pcb_false, method)) + pcb_board_set_changed_flag(pcb_true); + if (PCB_ACTION_ARG(1) == NULL) + free((char*)pattern); + } + 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_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_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; + + } + } + return 0; +} + +pcb_hid_action_t select_action_list[] = { + {"Select", 0, pcb_act_Select, + pcb_acth_Select, pcb_acts_Select} + , + {"Unselect", 0, pcb_act_Unselect, + pcb_acth_Unselect, pcb_acts_Unselect} +}; + +PCB_REGISTER_ACTIONS(select_action_list, NULL) Index: tags/1.2.7/src/stub_draw.c =================================================================== --- tags/1.2.7/src/stub_draw.c (nonexistent) +++ tags/1.2.7/src/stub_draw.c (revision 13657) @@ -0,0 +1,97 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#include "config.h" +#include "stub_draw.h" +#include "obj_text.h" +#include "obj_text_draw.h" + +/****** common code ******/ +void dummy_draw_text(pcb_hid_gc_t gc, const char *str) +{ + pcb_text_t t; + + pcb_gui->set_color(gc, "#FF0000"); + + t.X = 0; + t.Y = 0; + t.TextString = (char *)str; + t.Direction = 0; + t.fid = 0; /* use the default font */ + t.Scale = 150; + t.Flags = pcb_no_flags(); + pcb_text_draw_(&t, 0, 0); +} + +static pcb_bool dummy_mouse(void *widget, 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_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + dummy_draw_text(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_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(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)(void *widget, 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) +{ + dummy_draw_text(gc, "Can't render the font selector: the draw_fontsel plugin is not compiled and/or not loaded"); +} + +static pcb_text_t *dummy_fontsel_text = NULL; +static pcb_layer_t *dummy_fontsel_layer = NULL; +static int dummy_fontsel_type = 0; + +void (*pcb_stub_draw_fontsel)(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) = dummy_draw_fontsel; +pcb_bool (*pcb_stub_draw_fontsel_mouse_ev)(void *widget, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) = dummy_mouse; +pcb_text_t **pcb_stub_draw_fontsel_text_obj = &dummy_fontsel_text; +pcb_layer_t **pcb_stub_draw_fontsel_layer_obj = &dummy_fontsel_layer; +int *pcb_stub_draw_fontsel_text_type = &dummy_fontsel_type; Index: tags/1.2.7/src/stub_draw.h =================================================================== --- tags/1.2.7/src/stub_draw.h (nonexistent) +++ tags/1.2.7/src/stub_draw.h (revision 13657) @@ -0,0 +1,51 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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" + +/* fab */ +extern int (*pcb_stub_draw_fab_overhang)(void); +extern void (*pcb_stub_draw_fab)(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)(void *widget, 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); +extern pcb_bool (*pcb_stub_draw_fontsel_mouse_ev)(void *widget, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y); +extern pcb_text_t **pcb_stub_draw_fontsel_text_obj; +extern pcb_layer_t **pcb_stub_draw_fontsel_layer_obj; +extern int *pcb_stub_draw_fontsel_text_type; + +#endif Index: tags/1.2.7/src/stub_mincut.c =================================================================== --- tags/1.2.7/src/stub_mincut.c (nonexistent) +++ tags/1.2.7/src/stub_mincut.c (revision 13657) @@ -0,0 +1,41 @@ +/* + * 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. + * + */ + +#include "config.h" +#include +#include "stub_mincut.h" +#include "obj_common.h" + +static void stub_rat_proc_shorts_dummy(void) +{ +} + +static void stub_rat_found_short_dummy(pcb_any_obj_t *term, const char *with_net) +{ + /* original behavior: just warn at random pins/pads */ + PCB_FLAG_SET(PCB_FLAG_WARN, term); + + stub_rat_proc_shorts_dummy(); +} + +void (*pcb_stub_rat_found_short)(pcb_any_obj_t *term, const char *with_net) = stub_rat_found_short_dummy; +void (*pcb_stub_rat_proc_shorts)(void) = stub_rat_proc_shorts_dummy; Index: tags/1.2.7/src/stub_mincut.h =================================================================== --- tags/1.2.7/src/stub_mincut.h (nonexistent) +++ tags/1.2.7/src/stub_mincut.h (revision 13657) @@ -0,0 +1,27 @@ +/* + * 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. + * + */ + +#include "global_typedefs.h" + +extern void (*pcb_stub_rat_found_short)(pcb_any_obj_t *term, const char *with_net); +extern void (*pcb_stub_rat_proc_shorts)(void); + Index: tags/1.2.7/src/stub_stroke.c =================================================================== --- tags/1.2.7/src/stub_stroke.c (nonexistent) +++ tags/1.2.7/src/stub_stroke.c (revision 13657) @@ -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. + * + */ +#include "error.h" +#include "config.h" +#include "pcb_bool.h" + +pcb_bool pcb_mid_stroke = pcb_false; + +static void stub_stroke_record_dummy(int ev_x, int ev_y) +{ +} + +static void stub_stroke_start_dummy(void) +{ + pcb_message(PCB_MSG_WARNING, "Can not use libstroke: not compiled as a buildin and not loaded as a plugin\n"); +} + +void (*pcb_stub_stroke_record)(int ev_x, int ev_y) = stub_stroke_record_dummy; +void (*pcb_stub_stroke_start)(void) = stub_stroke_start_dummy; +void (*pcb_stub_stroke_finish)(void) = stub_stroke_start_dummy; Index: tags/1.2.7/src/stub_stroke.h =================================================================== --- tags/1.2.7/src/stub_stroke.h (nonexistent) +++ tags/1.2.7/src/stub_stroke.h (revision 13657) @@ -0,0 +1,26 @@ +/* + * 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. + * + */ + +extern pcb_bool pcb_mid_stroke; +extern void (*pcb_stub_stroke_record)(int ev_x, int ev_y); +extern void (*pcb_stub_stroke_start)(void); +extern void (*pcb_stub_stroke_finish)(void); Index: tags/1.2.7/src/stub_vendor.c =================================================================== --- tags/1.2.7/src/stub_vendor.c (nonexistent) +++ tags/1.2.7/src/stub_vendor.c (revision 13657) @@ -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. + * + */ + +#include "config.h" +#include "stub_vendor.h" + +static int stub_vendorDrillMap_dummy(int dia) +{ + return dia; +} + +static pcb_bool stub_vendorIsElementMappable_dummy(pcb_element_t *e) +{ + return pcb_false; +} + +int (*pcb_stub_vendor_drill_map)(int) = stub_vendorDrillMap_dummy; +pcb_bool (*pcb_stub_vendor_is_element_mappable)(pcb_element_t *) = stub_vendorIsElementMappable_dummy; + + Index: tags/1.2.7/src/stub_vendor.h =================================================================== --- tags/1.2.7/src/stub_vendor.h (nonexistent) +++ tags/1.2.7/src/stub_vendor.h (revision 13657) @@ -0,0 +1,32 @@ +/* + * 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. + * + */ + +#ifndef PCB_STUB_VENDOR_H +#define PCB_STUB_VENDOR_H + +#include "config.h" +#include "global_typedefs.h" + +extern int (*pcb_stub_vendor_drill_map)(int); +extern pcb_bool (*pcb_stub_vendor_is_element_mappable)(pcb_element_t *); + +#endif /* __VENDOR_H__ */ Index: tags/1.2.7/src/thermal.c =================================================================== --- tags/1.2.7/src/thermal.c (nonexistent) +++ tags/1.2.7/src/thermal.c (revision 13657) @@ -0,0 +1,807 @@ +/* + * 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. + * + */ + +#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; +} + + +pcb_polyarea_t *pcb_thermal_area_pin(pcb_board_t *pcb, pcb_pin_t *pin, pcb_layer_id_t lid) +{ + return ThermPoly(pcb, pin, lid); +} + +/* 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 { + 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 */ +#warning 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; + clrth = (line->Clearance + 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*2); + 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; + 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; + + switch(shp->shape) { + 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; + 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); + 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: + { + pcb_pstk_proto_t *proto = pcb_pstk_get_proto(ps); + return pcb_poly_from_circle(ps->x, ps->y, proto->hdia/2 + clearance); + } + case PCB_THERMAL_SOLID: return NULL; + + case PCB_THERMAL_ROUND: + case PCB_THERMAL_SHARP: + switch(shp->shape) { + 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; + 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_PIN: + case PCB_OBJ_VIA: + return pcb_thermal_area_pin(pcb, (pcb_pin_t *)obj, lid); + + 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/1.2.7/src/thermal.h =================================================================== --- tags/1.2.7/src/thermal.h (nonexistent) +++ tags/1.2.7/src/thermal.h (revision 13657) @@ -0,0 +1,62 @@ +/* + * 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. + * + */ + +#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_pin(pcb_board_t *pcb, pcb_pin_t *pin, 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/1.2.7/src/tool.c =================================================================== --- tags/1.2.7/src/tool.c (nonexistent) +++ tags/1.2.7/src/tool.c (revision 13657) @@ -0,0 +1,314 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include "tool.h" + +#include "board.h" +#include "conf_core.h" +#include "error.h" +#include "event.h" + +#warning tool TODO: remove this when pcb_crosshair_set_mode() got moved here +#include "crosshair.h" + +static void default_tool_reg(void); +static void default_tool_unreg(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; + pcb_crosshair_set_mode(id); + return 0; +} + +int pcb_tool_select_by_id(pcb_toolid_t id) +{ + if ((id < 0) || (id > vtp0_len(&pcb_tools))) + return -1; + pcb_crosshair_set_mode(id); + 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; + pcb_crosshair_set_mode(bestn); + return 0; +} + +/**** 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) + +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_TYPE_VIA: + *x = ((pcb_pin_t *) ptr2)->X; + *y = ((pcb_pin_t *) ptr2)->Y; + break; + case PCB_TYPE_LINE: + *x = ((pcb_line_t *) ptr2)->Point1.X; + *y = ((pcb_line_t *) ptr2)->Point1.Y; + break; + case PCB_TYPE_TEXT: + case PCB_TYPE_ELEMENT_NAME: + *x = ((pcb_text_t *) ptr2)->X; + *y = ((pcb_text_t *) ptr2)->Y; + break; + case PCB_TYPE_ELEMENT: + *x = ((pcb_element_t *) ptr2)->MarkX; + *y = ((pcb_element_t *) ptr2)->MarkY; + break; + case PCB_TYPE_POLY: + *x = ((pcb_poly_t *) ptr2)->Points[0].X; + *y = ((pcb_poly_t *) ptr2)->Points[0].Y; + break; + + case PCB_TYPE_LINE_POINT: + case PCB_TYPE_POLY_POINT: + *x = ((pcb_point_t *) ptr3)->X; + *y = ((pcb_point_t *) ptr3)->Y; + break; + case PCB_TYPE_ARC: + pcb_arc_get_end((pcb_arc_t *) ptr2, 0, x, y); + break; + case PCB_TYPE_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 */ + GetObjectBoundingBox(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_TYPE_ELEMENT || + pcb_crosshair.AttachedObject.Type == PCB_TYPE_VIA || + pcb_crosshair.AttachedObject.Type == PCB_TYPE_LINE || pcb_crosshair.AttachedObject.Type == PCB_TYPE_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); +} + + +#warning tool TODO: 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); +} + Index: tags/1.2.7/src/tool.h =================================================================== --- tags/1.2.7/src/tool.h (nonexistent) +++ tags/1.2.7/src/tool.h (revision 13657) @@ -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. + * + */ + +#ifndef PCB_TOOL_H +#define PCB_TOOL_H + +#include + +#include "global_typedefs.h" +#include "pcb_bool.h" + +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 (*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_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); + +/**** 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; + +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) */ + + +/**** 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/1.2.7/src/tool_arc.c =================================================================== --- tags/1.2.7/src/tool_arc.c (nonexistent) +++ tags/1.2.7/src/tool_arc.c (revision 13657) @@ -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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "board.h" +#include "crosshair.h" +#include "data.h" +#include "draw.h" +#include "search.h" +#include "tool.h" +#include "undo.h" + +#include "obj_arc_draw.h" + + +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_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_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_TYPE_ARC, CURRENT, arc, arc); + pcb_undo_inc_serial(); + pcb_added_lines++; + pcb_arc_invalidate_draw(CURRENT, arc); + 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) { + XORDrawAttachedArc(conf_core.design.line_thickness); + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawAttachedArc(conf_core.design.line_thickness + 2 * (PCB->Bloat + 1)); + 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_TYPE_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_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_notify_mode, + NULL, + pcb_tool_arc_adjust_attached_objects, + pcb_tool_arc_draw_attached, + pcb_tool_arc_undo_act, + NULL +}; Index: tags/1.2.7/src/tool_arc.h =================================================================== --- tags/1.2.7/src/tool_arc.h (nonexistent) +++ tags/1.2.7/src/tool_arc.h (revision 13657) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_arc; + +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/1.2.7/src/tool_arrow.c =================================================================== --- tags/1.2.7/src/tool_arrow.c (nonexistent) +++ tags/1.2.7/src/tool_arrow.c (revision 13657) @@ -0,0 +1,205 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "board.h" +#include "buffer.h" +#include "crosshair.h" +#include "data.h" +#include "hid_actions.h" +#include "remove.h" +#include "search.h" +#include "select.h" +#include "tool.h" +#include "undo.h" + + +/* 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_crosshair_save_mode(); + pcb_tool_is_saved = pcb_true; + pcb_crosshair_set_mode(PCB_MODE_PASTE_BUFFER); + } + else if (pcb_tool_note.Hit && !pcb_gui->shift_is_pressed()) { + pcb_box_t box; + + pcb_crosshair_save_mode(); + pcb_tool_is_saved = pcb_true; + pcb_crosshair_set_mode(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_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_LOOSE_SUBC) & ~PCB_TYPE_RATLINE; 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_pin_t *) ptr2)) { + pcb_tool_note.Hit = type; + pcb_tool_note.ptr1 = ptr1; + pcb_tool_note.ptr2 = ptr2; + pcb_tool_note.ptr3 = ptr3; + } + if (!pcb_tool_note.Moving && (type & (PCB_SELECT_TYPES | PCB_LOOSE_SUBC)) && PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr2)) + pcb_tool_note.Moving = pcb_true; + if ((pcb_tool_note.Hit && pcb_tool_note.Moving) || type == PCB_TYPE_NONE) + 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_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 { + 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_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, + pcb_tool_arrow_notify_mode, + pcb_tool_arrow_release_mode, + pcb_tool_arrow_adjust_attached_objects, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_arrow.h =================================================================== --- tags/1.2.7/src/tool_arrow.h (nonexistent) +++ tags/1.2.7/src/tool_arrow.h (revision 13657) @@ -0,0 +1,5 @@ +extern pcb_tool_t pcb_tool_arrow; + +void pcb_tool_arrow_notify_mode(void); +void pcb_tool_arrow_release_mode(void); +void pcb_tool_arrow_adjust_attached_objects(void); Index: tags/1.2.7/src/tool_buffer.c =================================================================== --- tags/1.2.7/src/tool_buffer.c (nonexistent) +++ tags/1.2.7/src/tool_buffer.c (revision 13657) @@ -0,0 +1,118 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "board.h" +#include "buffer.h" +#include "compat_misc.h" +#include "data.h" +#include "hid_actions.h" +#include "rtree.h" +#include "search.h" +#include "tool.h" +#include "undo.h" + +#include "obj_elem_draw.h" + + +void pcb_tool_buffer_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + pcb_text_t estr[PCB_MAX_ELEMENTNAMES]; + pcb_element_t *e = 0; + + if (pcb_gui->shift_is_pressed()) { + int type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_TYPE_ELEMENT | PCB_TYPE_SUBC, &ptr1, &ptr2, + &ptr3); + if (type == PCB_TYPE_ELEMENT) { + e = (pcb_element_t *) ptr1; + if (e) { + int i; + + memcpy(estr, e->Name, PCB_MAX_ELEMENTNAMES * sizeof(pcb_text_t)); + for (i = 0; i < PCB_MAX_ELEMENTNAMES; ++i) + estr[i].TextString = estr[i].TextString ? pcb_strdup(estr[i].TextString) : NULL; + pcb_element_remove(e); + } + } + } + if (pcb_buffer_copy_to_layout(PCB, pcb_tool_note.X, pcb_tool_note.Y)) + pcb_board_set_changed_flag(pcb_true); + if (e) { + int type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_TYPE_ELEMENT | PCB_TYPE_SUBC, &ptr1, &ptr2, + &ptr3); + if (type == PCB_TYPE_ELEMENT && ptr1) { + int i, save_n; + e = (pcb_element_t *) ptr1; + + save_n = PCB_ELEMNAME_IDX_VISIBLE(); + + for (i = 0; i < PCB_MAX_ELEMENTNAMES; i++) { + if (i == save_n) + pcb_elem_name_invalidate_erase(e); + pcb_r_delete_entry(PCB->Data->name_tree[i], (pcb_box_t *) & (e->Name[i])); + memcpy(&(e->Name[i]), &(estr[i]), sizeof(pcb_text_t)); + e->Name[i].Element = e; + pcb_text_bbox(pcb_font(PCB, 0, 1), &(e->Name[i])); + pcb_r_insert_entry(PCB->Data->name_tree[i], (pcb_box_t *) & (e->Name[i]), 0); + if (i == save_n) + pcb_elem_name_invalidate_draw(e); + } + } + } +} + +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_draw_attached(void) +{ + XORDrawBuffer(PCB_PASTEBUFFER); +} + +pcb_tool_t pcb_tool_buffer = { + "buffer", NULL, 100, + pcb_tool_buffer_notify_mode, + pcb_tool_buffer_release_mode, + NULL, + pcb_tool_buffer_draw_attached, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_buffer.h =================================================================== --- tags/1.2.7/src/tool_buffer.h (nonexistent) +++ tags/1.2.7/src/tool_buffer.h (revision 13657) @@ -0,0 +1,5 @@ +extern pcb_tool_t pcb_tool_buffer; + +void pcb_tool_buffer_notify_mode(void); +void pcb_tool_buffer_release_mode(void); +void pcb_tool_buffer_draw_attached(void); Index: tags/1.2.7/src/tool_copy.c =================================================================== --- tags/1.2.7/src/tool_copy.c (nonexistent) +++ tags/1.2.7/src/tool_copy.c (revision 13657) @@ -0,0 +1,100 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "copy.h" +#include "crosshair.h" +#include "search.h" +#include "tool.h" + + +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_TYPE_NONE) { + 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: + pcb_copy_obj(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, + pcb_crosshair.AttachedObject.Ptr3, pcb_tool_note.X - pcb_crosshair.AttachedObject.X, pcb_tool_note.Y - pcb_crosshair.AttachedObject.Y); + pcb_board_set_changed_flag(pcb_true); + + /* reset identifiers */ + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + 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_draw_attached(void) +{ + XORDrawMoveOrCopy(); +} + +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, + pcb_tool_copy_notify_mode, + pcb_tool_copy_release_mode, + NULL, + pcb_tool_copy_draw_attached, + pcb_tool_copy_undo_act, + NULL +}; Index: tags/1.2.7/src/tool_copy.h =================================================================== --- tags/1.2.7/src/tool_copy.h (nonexistent) +++ tags/1.2.7/src/tool_copy.h (revision 13657) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_copy; + +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/1.2.7/src/tool_insert.c =================================================================== --- tags/1.2.7/src/tool_insert.c (nonexistent) +++ tags/1.2.7/src/tool_insert.c (revision 13657) @@ -0,0 +1,130 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "compat_nls.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_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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_poly_t *) + pcb_crosshair.AttachedObject.Ptr2)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + break; + } + else { + /* get starting point of nearest segment */ + if (pcb_crosshair.AttachedObject.Type == PCB_TYPE_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_TYPE_POLY) + pcb_insert_point_in_object(PCB_TYPE_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_TYPE_NONE; + 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) +{ + XORDrawInsertPointObject(); +} + +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, + pcb_tool_insert_notify_mode, + NULL, + pcb_tool_insert_adjust_attached_objects, + pcb_tool_insert_draw_attached, + pcb_tool_insert_undo_act, + NULL +}; Index: tags/1.2.7/src/tool_insert.h =================================================================== --- tags/1.2.7/src/tool_insert.h (nonexistent) +++ tags/1.2.7/src/tool_insert.h (revision 13657) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_insert; + +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/1.2.7/src/tool_line.c =================================================================== --- tags/1.2.7/src/tool_line.c (nonexistent) +++ tags/1.2.7/src/tool_line.c (revision 13657) @@ -0,0 +1,421 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.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 "rats.h" +#include "search.h" +#include "tool.h" +#include "undo.h" + +#include "obj_line_draw.h" +#include "obj_pinvia_draw.h" +#include "obj_rat_draw.h" + + +static pcb_layer_t *last_layer; + + +/* creates points of a line (when clicked) */ +static void notify_line(void) +{ + int type = PCB_TYPE_NONE; + 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 */ + if (PCB->RatDraw && pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_PAD | PCB_TYPE_PIN, &ptr1, &ptr1, &ptr1) == PCB_TYPE_NONE) { + pcb_gui->beep(); + break; + } + if (conf_core.editor.auto_drc) { + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_VIA, &ptr1, &ptr2, &ptr3); + pcb_lookup_conn(pcb_crosshair.X, pcb_crosshair.Y, pcb_true, 1, PCB_FLAG_FOUND); + } + if (type == PCB_TYPE_PIN || type == PCB_TYPE_VIA) { + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X = ((pcb_pin_t *) ptr2)->X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y = ((pcb_pin_t *) ptr2)->Y; + } + else if (type == PCB_TYPE_PAD) { + pcb_pad_t *pad = (pcb_pad_t *) ptr2; + double d1 = pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, pad->Point1.X, pad->Point1.Y); + double d2 = pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, pad->Point2.X, pad->Point2.Y); + double dm = pcb_distance(pcb_crosshair.X, pcb_crosshair.Y, (pad->Point1.X + pad->Point2.X) / 2, (pad->Point1.Y + pad->Point2.Y)/2); + if ((dm <= d1) && (dm <= d2)) { /* prefer to snap to the middle of a pin if that's the closest */ + 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; + } + else if (d2 < d1) { /* else select the closest endpoint */ + pcb_crosshair.AttachedLine.Point1 = pcb_crosshair.AttachedLine.Point2 = pad->Point2; + } + else { + pcb_crosshair.AttachedLine.Point1 = pcb_crosshair.AttachedLine.Point2 = pad->Point1; + } + } + 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_crosshair_set_mode(PCB_MODE_LINE); + return; + } + + if (PCB->RatDraw) { + pcb_rat_t *line; + if ((line = pcb_rat_add_net())) { + pcb_added_lines++; + pcb_undo_add_obj_to_create(PCB_TYPE_RATLINE, 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_pin_t *via = 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 */ + if (PCB->ViaOn + && pcb_layer_get_group_(CURRENT) != pcb_layer_get_group_(last_layer) + && pcb_search_obj_by_location(PCB_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness / 2) == + PCB_TYPE_NONE + && (pcb_layer_flags_(CURRENT) & PCB_LYT_COPPER) + && (pcb_layer_flags_(last_layer) & PCB_LYT_COPPER) + && (!PCB->is_footprint) + && (via = pcb_via_new(PCB->Data, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness, + 2 * conf_core.design.clearance, 0, + conf_core.design.via_drilling_hole, NULL, + pcb_no_flags())) != NULL) { + pcb_obj_add_attribs(via, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + } + + /* 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(via) + pcb_via_invalidate_draw(via); + + 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_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_pin_t *via; + + pcb_added_lines++; + pcb_obj_add_attribs(line, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_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 */ + if (PCB->ViaOn + && 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_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness / 2) == PCB_TYPE_NONE + && (via = + pcb_via_new(PCB->Data, + pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + conf_core.design.via_thickness, + 2 * conf_core.design.clearance, 0, conf_core.design.via_drilling_hole, NULL, pcb_no_flags())) != NULL) { + pcb_obj_add_attribs(via, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + pcb_via_invalidate_draw(via); + } + /* 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; + } + 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_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_TYPE_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); + } + } + 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); + } +} + +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_TYPE_LINE | PCB_TYPE_RATLINE, &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_TYPE_LINE | PCB_TYPE_RATLINE, &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_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_TYPE_LINE | PCB_TYPE_RATLINE, &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_notify_mode, + NULL, + pcb_tool_line_adjust_attached_objects, + pcb_tool_line_draw_attached, + pcb_tool_line_undo_act, + pcb_tool_line_redo_act +}; Index: tags/1.2.7/src/tool_line.h =================================================================== --- tags/1.2.7/src/tool_line.h (nonexistent) +++ tags/1.2.7/src/tool_line.h (revision 13657) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_line; + +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/1.2.7/src/tool_lock.c =================================================================== --- tags/1.2.7/src/tool_lock.c (nonexistent) +++ tags/1.2.7/src/tool_lock.c (revision 13657) @@ -0,0 +1,104 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "change.h" +#include "data.h" +#include "draw.h" +#include "hid_actions.h" +#include "search.h" +#include "tool.h" +#include "tool_lock.h" + +#include "obj_elem_draw.h" + + +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_TYPEMASK_LOCK, &ptr1, &ptr2, &ptr3); + if (type == PCB_TYPE_ELEMENT) { + pcb_element_t *element = (pcb_element_t *) ptr2; + + PCB_FLAG_TOGGLE(PCB_FLAG_LOCK, element); + PCB_PIN_LOOP(element); + { + PCB_FLAG_TOGGLE(PCB_FLAG_LOCK, pin); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + PCB_FLAG_TOGGLE(PCB_FLAG_LOCK, pad); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, pad); + } + PCB_END_LOOP; + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, element); + /* always re-draw it since I'm too lazy + * to tell if a selected flag changed + */ + pcb_elem_invalidate_draw(element); + pcb_draw(); + pcb_hid_actionl("Report", "Object", NULL); + } + else if (type == PCB_TYPE_SUBC) { + pcb_subc_t *subc = (pcb_subc_t *)ptr2; + pcb_flag_change(PCB, PCB_CHGFLG_TOGGLE, PCB_FLAG_LOCK, PCB_TYPE_SUBC, ptr1, ptr2, ptr3); + + DrawSubc(subc); + pcb_draw(); + pcb_hid_actionl("Report", "Subc", NULL); + } + else if (type != PCB_TYPE_NONE) { + 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_hid_actionl("Report", "Object", NULL); + } +} + +pcb_tool_t pcb_tool_lock = { + "lock", NULL, 100, + pcb_tool_lock_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_lock.h =================================================================== --- tags/1.2.7/src/tool_lock.h (nonexistent) +++ tags/1.2.7/src/tool_lock.h (revision 13657) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_lock; + +void pcb_tool_lock_notify_mode(void); Index: tags/1.2.7/src/tool_move.c =================================================================== --- tags/1.2.7/src/tool_move.c (nonexistent) +++ tags/1.2.7/src/tool_move.c (revision 13657) @@ -0,0 +1,108 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "compat_nls.h" +#include "copy.h" +#include "crosshair.h" +#include "search.h" +#include "tool.h" + + +void pcb_tool_move_notify_mode(void) +{ + 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_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) pcb_crosshair.AttachedObject.Ptr2)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + } + 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: + pcb_move_obj_and_rubberband(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, + pcb_crosshair.AttachedObject.Ptr3, + pcb_tool_note.X - pcb_crosshair.AttachedObject.X, pcb_tool_note.Y - pcb_crosshair.AttachedObject.Y); + pcb_crosshair_set_local_ref(0, 0, pcb_false); + pcb_board_set_changed_flag(pcb_true); + + /* reset identifiers */ + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + 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_draw_attached(void) +{ + XORDrawMoveOrCopy(); +} + +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, + pcb_tool_move_notify_mode, + pcb_tool_move_release_mode, + NULL, + pcb_tool_move_draw_attached, + pcb_tool_move_undo_act, + NULL +}; Index: tags/1.2.7/src/tool_move.h =================================================================== --- tags/1.2.7/src/tool_move.h (nonexistent) +++ tags/1.2.7/src/tool_move.h (revision 13657) @@ -0,0 +1,6 @@ +extern pcb_tool_t pcb_tool_move; + +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/1.2.7/src/tool_poly.c =================================================================== --- tags/1.2.7/src/tool_poly.c (nonexistent) +++ tags/1.2.7/src/tool_poly.c (revision 13657) @@ -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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "crosshair.h" +#include "hid_actions.h" +#include "polygon.h" +#include "tool.h" + + +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_hid_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_hid_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_line_adjust_attached(); +} + +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) { + XORPolygon(&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, + 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, +}; Index: tags/1.2.7/src/tool_poly.h =================================================================== --- tags/1.2.7/src/tool_poly.h (nonexistent) +++ tags/1.2.7/src/tool_poly.h (revision 13657) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_poly; + +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/1.2.7/src/tool_polyhole.c =================================================================== --- tags/1.2.7/src/tool_polyhole.c (nonexistent) +++ tags/1.2.7/src/tool_polyhole.c (revision 13657) @@ -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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "compat_nls.h" +#include "crosshair.h" +#include "hid_actions.h" +#include "polygon.h" +#include "search.h" +#include "tool.h" + + +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_TYPE_POLY, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + + if (pcb_crosshair.AttachedObject.Type == PCB_TYPE_NONE) { + 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, the object is locked\n")); + pcb_crosshair.AttachedObject.Type = PCB_TYPE_NONE; + 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_hid_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_hid_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_line_adjust_attached(); +} + +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) { + XORPolygon(&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, + 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 +}; Index: tags/1.2.7/src/tool_polyhole.h =================================================================== --- tags/1.2.7/src/tool_polyhole.h (nonexistent) +++ tags/1.2.7/src/tool_polyhole.h (revision 13657) @@ -0,0 +1,7 @@ +extern pcb_tool_t pcb_tool_polyhole; + +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/1.2.7/src/tool_rectangle.c =================================================================== --- tags/1.2.7/src/tool_rectangle.c (nonexistent) +++ tags/1.2.7/src/tool_rectangle.c (revision 13657) @@ -0,0 +1,110 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.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_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); + + 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_TYPE_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; + } +} + +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, + pcb_tool_rectangle_notify_mode, + NULL, + pcb_tool_rectangle_adjust_attached_objects, + NULL, + pcb_tool_rectangle_anydo_act, + pcb_tool_rectangle_anydo_act +}; Index: tags/1.2.7/src/tool_rectangle.h =================================================================== --- tags/1.2.7/src/tool_rectangle.h (nonexistent) +++ tags/1.2.7/src/tool_rectangle.h (revision 13657) @@ -0,0 +1,5 @@ +extern pcb_tool_t pcb_tool_rectangle; + +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/1.2.7/src/tool_remove.c =================================================================== --- tags/1.2.7/src/tool_remove.c (nonexistent) +++ tags/1.2.7/src/tool_remove.c (revision 13657) @@ -0,0 +1,68 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "compat_nls.h" +#include "event.h" +#include "hid_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; + int type; + + if ((type = pcb_search_screen(pcb_tool_note.X, pcb_tool_note.Y, PCB_REMOVE_TYPES | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_line_t *) ptr2)) { + pcb_message(PCB_MSG_WARNING, _("Sorry, the object is locked\n")); + return; + } + if (type == PCB_TYPE_ELEMENT) + pcb_event(PCB_EVENT_RUBBER_REMOVE_ELEMENT, "ppp", ptr1, ptr2, ptr3); + pcb_remove_object(type, ptr1, ptr2, ptr3); + pcb_undo_inc_serial(); + pcb_board_set_changed_flag(pcb_true); + } +} + +pcb_tool_t pcb_tool_remove = { + "remove", NULL, 100, + pcb_tool_remove_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_remove.h =================================================================== --- tags/1.2.7/src/tool_remove.h (nonexistent) +++ tags/1.2.7/src/tool_remove.h (revision 13657) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_remove; + +void pcb_tool_remove_notify_mode(void); Index: tags/1.2.7/src/tool_rotate.c =================================================================== --- tags/1.2.7/src/tool_rotate.c (nonexistent) +++ tags/1.2.7/src/tool_rotate.c (revision 13657) @@ -0,0 +1,52 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "hid_actions.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()? (PCB_SWAP_IDENT ? 1 : 3) + : (PCB_SWAP_IDENT ? 3 : 1)); +} + +pcb_tool_t pcb_tool_rotate = { + "rotate", NULL, 100, + pcb_tool_rotate_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_rotate.h =================================================================== --- tags/1.2.7/src/tool_rotate.h (nonexistent) +++ tags/1.2.7/src/tool_rotate.h (revision 13657) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_rotate; + +void pcb_tool_rotate_notify_mode(void); Index: tags/1.2.7/src/tool_text.c =================================================================== --- tags/1.2.7/src/tool_text.c (nonexistent) +++ tags/1.2.7/src/tool_text.c (revision 13657) @@ -0,0 +1,75 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "board.h" +#include "compat_nls.h" +#include "data.h" +#include "draw.h" +#include "hid_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_gui->prompt_for(_("Enter 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_font(PCB, conf_core.design.text_font_id, 1), pcb_tool_note.X, + pcb_tool_note.Y, 0, conf_core.design.text_scale, string, pcb_flag_make(flag))) != NULL) { + pcb_undo_add_obj_to_create(PCB_TYPE_TEXT, CURRENT, text, text); + pcb_undo_inc_serial(); + pcb_text_invalidate_draw(CURRENT, text); + pcb_draw(); + } + } + free(string); + } +} + +pcb_tool_t pcb_tool_text = { + "text", NULL, 100, + pcb_tool_text_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_text.h =================================================================== --- tags/1.2.7/src/tool_text.h (nonexistent) +++ tags/1.2.7/src/tool_text.h (revision 13657) @@ -0,0 +1,3 @@ +extern pcb_tool_t pcb_tool_text; + +void pcb_tool_text_notify_mode(void); Index: tags/1.2.7/src/tool_thermal.c =================================================================== --- tags/1.2.7/src/tool_thermal.c (nonexistent) +++ tags/1.2.7/src/tool_thermal.c (revision 13657) @@ -0,0 +1,123 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" + +#include "action_helper.h" +#include "board.h" +#include "change.h" +#include "data.h" +#include "hid_actions.h" +#include "obj_pstk.h" +#include "search.h" +#include "thermal.h" +#include "tool.h" + +static void tool_thermal_on_pinvia(int type, void *ptr1, void *ptr2, void *ptr3) +{ + if (pcb_gui->shift_is_pressed()) { + int tstyle = PCB_FLAG_THERM_GET(INDEXOFCURRENT, (pcb_pin_t *) ptr3); + tstyle++; + if (tstyle > 5) + tstyle = 1; + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, tstyle, INDEXOFCURRENT); + } + else if (PCB_FLAG_THERM_GET(INDEXOFCURRENT, (pcb_pin_t *) ptr3)) + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, 0, INDEXOFCURRENT); + else + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, PCB->ThermStyle, INDEXOFCURRENT); +} + +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 + }; + 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_TYPE_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_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + && !PCB_FLAG_TEST(PCB_FLAG_HOLE, (pcb_pin_t *) ptr3)) { + if (type == PCB_TYPE_PSTK) + pcb_tool_thermal_on_pstk((pcb_pstk_t *)ptr2, INDEXOFCURRENT); + else + tool_thermal_on_pinvia(type, ptr1, ptr2, ptr3); + } +} + +pcb_tool_t pcb_tool_thermal = { + "thermal", NULL, 100, + pcb_tool_thermal_notify_mode, + NULL, + NULL, + NULL, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_thermal.h =================================================================== --- tags/1.2.7/src/tool_thermal.h (nonexistent) +++ tags/1.2.7/src/tool_thermal.h (revision 13657) @@ -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/1.2.7/src/tool_via.c =================================================================== --- tags/1.2.7/src/tool_via.c (nonexistent) +++ tags/1.2.7/src/tool_via.c (revision 13657) @@ -0,0 +1,120 @@ +/* + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "conf_core.h" + +#include "action_helper.h" +#include "board.h" +#include "brave.h" +#include "change.h" +#include "compat_nls.h" +#include "data.h" +#include "draw.h" +#include "tool.h" +#include "tool_thermal.h" +#include "undo.h" + +#include "obj_pinvia_draw.h" +#include "obj_pstk_draw.h" + +#warning padstack TODO: 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->ViaOn) { + pcb_message(PCB_MSG_WARNING, _("You must turn via visibility on before\n" "you can place vias\n")); + return; + } + + if (pcb_brave & PCB_BRAVE_PSTK_VIA) { + pcb_pstk_t *ps = pcb_pstk_new_compat_via(PCB->Data, 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_TYPE_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(); + } + else { + pcb_pin_t *via; + if ((via = pcb_via_new(PCB->Data, pcb_tool_note.X, pcb_tool_note.Y, + conf_core.design.via_thickness, 2 * conf_core.design.clearance, + 0, conf_core.design.via_drilling_hole, NULL, pcb_no_flags())) != NULL) { + pcb_obj_add_attribs(via, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + if (pcb_gui->shift_is_pressed()) + pcb_chg_obj_thermal(PCB_TYPE_VIA, via, via, via, PCB->ThermStyle, INDEXOFCURRENT); + pcb_undo_inc_serial(); + pcb_via_invalidate_draw(via); + pcb_draw(); + } + } +} + +void pcb_tool_via_draw_attached(void) +{ + /* Make a dummy via structure to draw from */ + pcb_pin_t via; + via.X = pcb_crosshair.X; + via.Y = pcb_crosshair.Y; + via.Thickness = conf_core.design.via_thickness; + via.Clearance = 2 * conf_core.design.clearance; + via.DrillingHole = conf_core.design.via_drilling_hole; + via.Mask = 0; + via.Flags = pcb_no_flags(); + + pcb_gui->thindraw_pcb_pv(pcb_crosshair.GC, pcb_crosshair.GC, &via, pcb_true, pcb_false); + + 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); + XORDrawPinViaDRCOutline(&via,PCB->Bloat); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } +} + +pcb_tool_t pcb_tool_via = { + "via", NULL, 100, + pcb_tool_via_notify_mode, + NULL, + NULL, + pcb_tool_via_draw_attached, + NULL, + NULL +}; Index: tags/1.2.7/src/tool_via.h =================================================================== --- tags/1.2.7/src/tool_via.h (nonexistent) +++ tags/1.2.7/src/tool_via.h (revision 13657) @@ -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/1.2.7/src/undo.c =================================================================== --- tags/1.2.7/src/undo.c (nonexistent) +++ tags/1.2.7/src/undo.c (revision 13657) @@ -0,0 +1,274 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 "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 "compat_nls.h" + +#include "obj_elem_draw.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 */ +static uundo_list_t pcb_uundo; + +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, unique; + + unique = conf_core.editor.unique_names; + conf_force_set_bool(conf_core.editor.unique_names, 0); + + 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(); + + /* restore the unique flag setting */ + conf_force_set_bool(conf_core.editor.unique_names, unique); + + return res; +} + +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 */ + res = uundo_redo(&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(); + + 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_gui->confirm_dialog("OK to clear 'undo' buffer?", 0))) + uundo_list_clear(&pcb_uundo); +} + +/* --------------------------------------------------------------------------- + * 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); +} + +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 Index: tags/1.2.7/src/undo.h =================================================================== --- tags/1.2.7/src/undo.h (nonexistent) +++ tags/1.2.7/src/undo.h (revision 13657) @@ -0,0 +1,62 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#ifndef PCB_UNDO_H +#define PCB_UNDO_H + +#include +#include + +/* Temporary for compatibility */ +#include "undo_old.h" + +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); +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); + + +/* 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/1.2.7/src/undo_act.c =================================================================== --- tags/1.2.7/src/undo_act.c (nonexistent) +++ tags/1.2.7/src/undo_act.c (revision 13657) @@ -0,0 +1,193 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "action_helper.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."; + +/* %start-doc actions Atomic + +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 @code{Save}, +delete the rats, @code{Restore}, add the rats - using the same serial +number as the deletes, then @code{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. + +@table @code + +@item Save +Saves the undo serial number. + +@item Restore +Returns it to the last saved number. + +@item Close +Sets it to 1 greater than the last save. + +@item Block +Does a Restore if there was nothing to undo, else does a Close. + +@end table + +%end-doc */ + +int pcb_act_Atomic(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (argc != 1) + PCB_ACT_FAIL(Atomic); + + switch (pcb_funchash_get(argv[0], NULL)) { + 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; + } + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Undo[] = "undo()\n" "undo(ClearList)"; + +static const char pcb_acth_Undo[] = "Undo recent changes."; + +/* %start-doc actions Undo + +The unlimited undo feature of @code{Pcb} allows you to recover from +most operations that materially affect you work. Calling +@code{pcb_undo()} without any parameter recovers from the last (non-undo) +operation. @code{ClearList} is used to release the allocated +memory. @code{ClearList} is called whenever a new layout is started or +loaded. See also @code{Redo} and @code{Atomic}. + +Note that undo groups operations by serial number; changes with the +same serial number will be undone (or redone) as a group. See +@code{Atomic}. + +%end-doc */ + +int pcb_act_Undo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + 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) { + switch (pcb_funchash_get(function, NULL)) { + /* clear 'undo objects' list */ + case F_ClearList: + pcb_undo_clear_list(pcb_false); + break; + } + } + pcb_notify_crosshair_change(pcb_true); + return 0; +} + +/* --------------------------------------------------------------------------- */ + +static const char pcb_acts_Redo[] = "redo()"; + +static const char pcb_acth_Redo[] = "Redo recent \"undo\" operations."; + +/* %start-doc actions Redo + +This routine 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. + +%end-doc */ + +int pcb_act_Redo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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); + return 0; +} + + +pcb_hid_action_t undo_action_list[] = { + {"Atomic", 0, pcb_act_Atomic, + pcb_acth_Atomic, pcb_acts_Atomic} + , + {"Undo", 0, pcb_act_Undo, + pcb_acth_Undo, pcb_acts_Undo} + , + {"Redo", 0, pcb_act_Redo, + pcb_acth_Redo, pcb_acts_Redo} +}; + +PCB_REGISTER_ACTIONS(undo_action_list, NULL) Index: tags/1.2.7/src/undo_act.h =================================================================== --- tags/1.2.7/src/undo_act.h (nonexistent) +++ tags/1.2.7/src/undo_act.h (revision 13657) @@ -0,0 +1,4 @@ +/* Publish actions - these may be useful for other actions */ +int pcb_act_Undo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); +int pcb_act_Redo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); +int pcb_act_Atomic(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y); Index: tags/1.2.7/src/undo_old.c =================================================================== --- tags/1.2.7/src/undo_old.c (nonexistent) +++ tags/1.2.7/src/undo_old.c (revision 13657) @@ -0,0 +1,1425 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 "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 "compat_nls.h" + +#include "obj_elem_draw.h" +#include "obj_poly_draw.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 UndoMirror(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 UndoChangeMaskSize(UndoListTypePtr); +static pcb_bool UndoClearPoly(UndoListTypePtr); + + +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); + strcpy(dst, res); +#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, int ID, int 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_TYPE_NONE) { + 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_TYPE_NONE) { + 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_TYPE_NONE) { + 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_TYPE_NONE) { + 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 'change oinnum' operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoChangePinnum(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_TYPE_NONE) { + Entry->Data.ChangeName.Name = (char *) (pcb_chg_obj_pinnum(type, ptr1, ptr2, ptr3, Entry->Data.ChangeName.Name)); + return (pcb_true); + } + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * recovers an object from a 2ndSize 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_TYPE_NONE) { + swap = ((pcb_pin_t *) ptr2)->DrillingHole; + if (pcb_undo_and_draw) + pcb_erase_obj(type, ptr1, ptr2); + ((pcb_pin_t *) ptr2)->DrillingHole = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_draw_obj((pcb_any_obj_t *)ptr2); + 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_TYPE_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, 0); + 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_TYPE_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, 0); + 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_TYPE_NONE) { + swap = ((pcb_pin_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_pin_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 mask size change operation + */ +static pcb_bool UndoChangeMaskSize(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_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_PAD)) { + swap = (type == PCB_TYPE_PAD ? ((pcb_pad_t *) ptr2)->Mask : ((pcb_pin_t *) ptr2)->Mask); + if (pcb_undo_and_draw) + pcb_erase_obj(type, ptr1, ptr2); + if (type == PCB_TYPE_PAD) + ((pcb_pad_t *) ptr2)->Mask = Entry->Data.Size; + else + ((pcb_pin_t *) ptr2)->Mask = Entry->Data.Size; + 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); + if (type == PCB_TYPE_ELEMENT_NAME) + ptr1e = NULL; + else + ptr1e = ptr1; + + if (type != PCB_TYPE_NONE) { + /* Wow! can any object be treated as a pin type for size change?? */ + /* pins, vias, lines, and arcs can. Text can't but it has it's own mechanism */ + swap = ((pcb_pin_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_pin_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 FLAG change operation + */ +static pcb_bool UndoFlag(UndoListTypePtr Entry) +{ + void *ptr1, *ptr1e, *ptr2, *ptr3; + int type; + pcb_flag_t swap; + int must_redraw; + + /* lookup entry by ID */ + type = pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_TYPE_NONE) { + pcb_flag_t f1, f2; + pcb_pin_t *pin = (pcb_pin_t *) ptr2; + + if ((type == PCB_TYPE_ELEMENT) || (type == PCB_TYPE_ELEMENT_NAME)) + ptr1e = NULL; + else + ptr1e = ptr1; + + swap = pin->Flags; + + must_redraw = 0; + f1 = pcb_flag_mask(pin->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); + + pin->Flags = Entry->Data.Flags; + + Entry->Data.Flags = swap; + + 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)); + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * recovers an object from a mirror operation + * returns pcb_true if anything has been recovered + */ +static pcb_bool UndoMirror(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_TYPE_ELEMENT) { + pcb_element_t *element = (pcb_element_t *) ptr3; + if (pcb_undo_and_draw) + pcb_elem_invalidate_erase(element); + pcb_element_mirror(PCB->Data, element, Entry->Data.Move.DY); + if (pcb_undo_and_draw) + pcb_elem_invalidate_draw(element); + return (pcb_true); + } + pcb_message(PCB_MSG_ERROR, "hace Internal error: UndoMirror on object type %d\n", type); + 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_TYPE_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_TYPE_NONE) { + 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; + 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_TYPE_NONE) { + 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; + + /* lookup entry by it's ID */ + type = pcb_search_obj_by_id(pcb_removelist, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_TYPE_NONE) { + pcb_move_obj_to_buffer(PCB, PCB->Data, pcb_removelist, type, ptr1, ptr2, ptr3); + if (pcb_undo_and_draw) + DrawRecoveredObject((pcb_any_obj_t *)ptr2); + Entry->Type = PCB_UNDO_CREATE; + return (pcb_true); + } + 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_TYPE_NONE) { + 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_TYPE_POLY); + type = pcb_search_obj_by_id(PCB->Data, (void **) &layer, (void **) &polygon, &ptr3, Entry->ID, Entry->Kind); + switch (type) { + case PCB_TYPE_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_TYPE_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_TYPE_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(Entry->Kind == PCB_TYPE_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_TYPE_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_TYPE_POLY; + Entry->Type = PCB_UNDO_REMOVE_POINT; + Entry->Data.RemovedPoint.Index = point_idx; + pcb_destroy_object(PCB->Data, PCB_TYPE_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_TYPE_NONE) + return pcb_false; + + type = pcb_search_obj_by_id(PCB->Data, &ptr1b, &ptr2b, &ptr3b, Entry->ID, Entry->Kind); + if (type == PCB_TYPE_NONE) + 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_TYPE_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_TYPE_POLY); + return UndoSwapCopiedObject(Entry); +} + +/* --------------------------------------------------------------------------- + * recovers an inserted polygon point + * returns pcb_true on success + */ +static pcb_bool UndoInsertContour(UndoListTypePtr Entry) +{ + assert(Entry->Kind == PCB_TYPE_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; + + 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; +} + +/* --------------------------------------------------------------------------- + * undo a netlist change + * returns pcb_true on success + */ +static pcb_bool UndoNetlistChange(UndoListTypePtr Entry) +{ + NetlistChangeTypePtr l = &Entry->Data.NetlistChange; + unsigned int i, j; + pcb_lib_t *lib, *saved; + + lib = l->lib; + saved = l->old; + + /* iterate over each net */ + for (i = 0; i < lib->MenuN; i++) { + free(lib->Menu[i].Name); + free(lib->Menu[i].directory); + free(lib->Menu[i].Style); + + /* iterate over each pin on the net */ + for (j = 0; j < lib->Menu[i].EntryN; j++) { + if (!lib->Menu[i].Entry[j].ListEntry_dontfree) + free((char*)lib->Menu[i].Entry[j].ListEntry); + + free((char*)lib->Menu[i].Entry[j].Package); + free((char*)lib->Menu[i].Entry[j].Value); + free((char*)lib->Menu[i].Entry[j].Description); + } + } + + free(lib->Menu); + + *lib = *saved; + + pcb_netlist_changed(0); + 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_CHANGEPINNUM: + if (UndoChangePinnum(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_CHANGECLEARSIZE: + if (UndoChangeClearSize(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGEMASKSIZE: + if (UndoChangeMaskSize(ptr)) + return 0; + break; + + case PCB_UNDO_CHANGE2NDSIZE: + if (UndoChange2ndSize(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_NETLISTCHANGE: + if (UndoNetlistChange(ptr)) + return 0; + break; + + case PCB_UNDO_MIRROR: + if (UndoMirror(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 object to the list of mirrored objects + */ +void pcb_undo_add_obj_to_mirror(int Type, void *Ptr1, void *Ptr2, void *Ptr3, pcb_coord_t yoff) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_MIRROR, PCB_OBJECT_ID(Ptr3), Type); + undo->Data.Move.DY = yoff; + } +} + +/* --------------------------------------------------------------------------- + * 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, pcb_uint8_t 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) +{ + if (Locked) + return; + + if (!pcb_removelist) + pcb_removelist = pcb_buffer_new(NULL); + + GetUndoSlot(PCB_UNDO_REMOVE, PCB_OBJECT_ID(Ptr3), Type); + 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_TYPE_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_TYPE_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 with changed pinnums + */ +void pcb_undo_add_obj_to_change_pinnum(int Type, void *Ptr1, void *Ptr2, void *Ptr3, char *OldName) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGEPINNUM, 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 + */ +extern unsigned long pcb_obj_type2oldtype(pcb_objtype_t type); +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), pcb_obj_type2oldtype(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_TYPE_PIN: + case PCB_TYPE_VIA: + undo->Data.Size = ((pcb_pin_t *) ptr2)->Thickness; + break; + case PCB_TYPE_LINE: + case PCB_TYPE_ELEMENT_LINE: + undo->Data.Size = ((pcb_line_t *) ptr2)->Thickness; + break; + case PCB_TYPE_TEXT: + case PCB_TYPE_ELEMENT_NAME: + undo->Data.Size = ((pcb_text_t *) ptr2)->Scale; + break; + case PCB_TYPE_PAD: + undo->Data.Size = ((pcb_pad_t *) ptr2)->Thickness; + break; + case PCB_TYPE_ARC: + case PCB_TYPE_ELEMENT_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_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_TYPE_PIN: + case PCB_TYPE_VIA: + undo->Data.Size = ((pcb_pin_t *) ptr2)->Clearance; + break; + case PCB_TYPE_LINE: + undo->Data.Size = ((pcb_line_t *) ptr2)->Clearance; + break; + case PCB_TYPE_PAD: + undo->Data.Size = ((pcb_pad_t *) ptr2)->Clearance; + break; + case PCB_TYPE_ARC: + undo->Data.Size = ((pcb_arc_t *) ptr2)->Clearance; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with Size changes + */ +void pcb_undo_add_obj_to_mask_size(int Type, void *ptr1, void *ptr2, void *ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_CHANGEMASKSIZE, PCB_OBJECT_ID(ptr2), Type); + switch (Type) { + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + undo->Data.Size = ((pcb_pin_t *) ptr2)->Mask; + break; + case PCB_TYPE_PAD: + undo->Data.Size = ((pcb_pad_t *) ptr2)->Mask; + break; + } + } +} + +/* --------------------------------------------------------------------------- + * adds an object to the list of objects with 2ndSize 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_CHANGE2NDSIZE, PCB_OBJECT_ID(ptr2), Type); + if (Type == PCB_TYPE_PIN || Type == PCB_TYPE_VIA) + undo->Data.Size = ((pcb_pin_t *) ptr2)->DrillingHole; + } +} + +/* --------------------------------------------------------------------------- + * 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) +{ + 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; + } +} + +/* --------------------------------------------------------------------------- + * adds a netlist change to the undo list + */ +void pcb_undo_add_netlist_lib(pcb_lib_t *lib) +{ + UndoListTypePtr undo; + unsigned int i, j; + pcb_lib_t *old; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_NETLISTCHANGE, 0, 0); + /* keep track of where the data needs to go */ + undo->Data.NetlistChange.lib = lib; + + /* and what the old data is that we'll need to restore */ + undo->Data.NetlistChange.old = (pcb_lib_t *) malloc(sizeof(pcb_lib_t *)); + old = undo->Data.NetlistChange.old; + old->MenuN = lib->MenuN; + old->MenuMax = lib->MenuMax; + old->Menu = (pcb_lib_menu_t *) malloc(old->MenuMax * sizeof(pcb_lib_menu_t)); + if (old->Menu == NULL) { + fprintf(stderr, "malloc() failed in AddNetlistLibToUndoList\n"); + exit(1); + } + + /* iterate over each net */ + for (i = 0; i < lib->MenuN; i++) { + old->Menu[i].EntryN = lib->Menu[i].EntryN; + old->Menu[i].EntryMax = lib->Menu[i].EntryMax; + + old->Menu[i].Name = lib->Menu[i].Name ? pcb_strdup(lib->Menu[i].Name) : NULL; + + old->Menu[i].directory = lib->Menu[i].directory ? pcb_strdup(lib->Menu[i].directory) : NULL; + + old->Menu[i].Style = lib->Menu[i].Style ? pcb_strdup(lib->Menu[i].Style) : NULL; + + + old->Menu[i].Entry = (pcb_lib_entry_t *) malloc(old->Menu[i].EntryMax * sizeof(pcb_lib_entry_t)); + if (old->Menu[i].Entry == NULL) { + fprintf(stderr, "malloc() failed in AddNetlistLibToUndoList\n"); + exit(1); + } + + /* iterate over each pin on the net */ + for (j = 0; j < lib->Menu[i].EntryN; j++) { + + old->Menu[i].Entry[j].ListEntry = lib->Menu[i].Entry[j].ListEntry ? pcb_strdup(lib->Menu[i].Entry[j].ListEntry) : NULL; + old->Menu[i].Entry[j].ListEntry_dontfree = 0; + + old->Menu[i].Entry[j].Package = lib->Menu[i].Entry[j].Package ? pcb_strdup(lib->Menu[i].Entry[j].Package) : NULL; + + old->Menu[i].Entry[j].Value = lib->Menu[i].Entry[j].Value ? pcb_strdup(lib->Menu[i].Entry[j].Value) : NULL; + + old->Menu[i].Entry[j].Description = + lib->Menu[i].Entry[j].Description ? pcb_strdup(lib->Menu[i].Entry[j].Description) : NULL; + + + } + } + + } +} + +#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_CHANGE2NDSIZE: return "change2ndsize"; + case PCB_UNDO_MIRROR: return "mirror"; + case PCB_UNDO_OTHERSIDE: return "otherside"; + case PCB_UNDO_CHANGECLEARSIZE: return "chngeclearsize"; + case PCB_UNDO_CHANGEMASKSIZE: return "changemasksize"; + case PCB_UNDO_CHANGEANGLES: return "changeangles"; + case PCB_UNDO_CHANGERADII: return "changeradii"; + case PCB_UNDO_LAYERMOVE: return "layermove"; + case PCB_UNDO_CLEAR: return "clear"; + case PCB_UNDO_NETLISTCHANGE: return "netlistchange"; + case PCB_UNDO_CHANGEPINNUM: return "changepinnum"; + } + 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: + case PCB_UNDO_CHANGEPINNUM: + 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_TYPE_NONE) + pcb_destroy_object(pcb_removelist, type, ptr1, ptr2, ptr3); + break; + default: + break; + } +} Index: tags/1.2.7/src/undo_old.h =================================================================== --- tags/1.2.7/src/undo_old.h (nonexistent) +++ tags/1.2.7/src/undo_old.h (revision 13657) @@ -0,0 +1,97 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* old undo infra: should be replaced by per operation local undo */ + +#ifndef PCB_UNDO_OLD_H +#define PCB_UNDO_OLD_H + +#include "library.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, pcb_uint8_t); +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_obj_to_mirror(int, void *, void *, void *, pcb_coord_t); +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, void *, void *, void *); +void pcb_undo_add_obj_to_clear_size(int, void *, void *, void *); +void pcb_undo_add_obj_to_mask_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); +void pcb_undo_add_netlist_lib(pcb_lib_t *); + +/* --------------------------------------------------------------------------- + * 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_CHANGE2NDSIZE = 0x001000, /* change 2ndSize of object */ + PCB_UNDO_MIRROR = 0x002000, /* change side of board */ + PCB_UNDO_CHANGECLEARSIZE = 0x004000, /* change clearance size */ + PCB_UNDO_CHANGEMASKSIZE = 0x008000, /* change mask 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_NETLISTCHANGE = 0x080000, /* netlist change */ + PCB_UNDO_CHANGEPINNUM = 0x100000, /* change of pin number */ + 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_op_t; + +const char *undo_type2str(int type); + +#endif Index: tags/1.2.7/src/undo_old_str.h =================================================================== --- tags/1.2.7/src/undo_old_str.h (nonexistent) +++ tags/1.2.7/src/undo_old_str.h (revision 13657) @@ -0,0 +1,66 @@ +#warning cleanup TODO: 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 { /* 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; +} 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_lib_t *old; + pcb_lib_t *lib; +} NetlistChangeType, *NetlistChangeTypePtr; + +typedef struct { /* holds information about an operation */ + int Serial, /* serial number of operation */ + Type, /* type of operation */ + Kind, /* type of object with given ID */ + ID; /* object ID */ + union { /* some additional information */ + ChangeNameType ChangeName; + MoveType Move; + 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/1.2.7/src/unit.c =================================================================== --- tags/1.2.7/src/unit.c (nonexistent) +++ tags/1.2.7/src/unit.c (revision 13657) @@ -0,0 +1,259 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Andrew Poelstra, 16966 60A Ave, V3S 8X5 Surrey, BC, Canada + * asp11@sfu.ca + * + */ +#include "config.h" +#include +#include +#include +#include "compat_misc.h" +#include "compat_nls.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); + } +} + +/* This list -must- contain all printable units from the above list */ +/* For now I have just copy/pasted the same values for all metric + * units and the same values for all imperial ones */ +pcb_increments_t pcb_increments[] = { + /* TABLE FORMAT | default | min | max + * grid | | | + * size | | | + * line | | | + * clear | | | + */ + {"km", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"m", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"cm", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"mm", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"um", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"du", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), /* du = eagle bin 0.1 micron = "decimicron" unit */ + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + {"nm", PCB_MM_TO_COORD3(0.1, 0.01, 1.0), + PCB_MM_TO_COORD3(0.2, 0.01, 0.5), + PCB_MM_TO_COORD3(0.1, 0.005, 0.5), + PCB_MM_TO_COORD3(0.05, 0.005, 0.5)}, + + {"cmil", PCB_MIL_TO_COORD3(5, 1, 25), + PCB_MIL_TO_COORD3(10, 1, 10), + PCB_MIL_TO_COORD3(5, 0.5, 10), + PCB_MIL_TO_COORD3(2, 0.5, 10)}, + {"dmil", PCB_MIL_TO_COORD3(5, 1, 25), /* kicad legacy decimil unit */ + PCB_MIL_TO_COORD3(10, 1, 10), + PCB_MIL_TO_COORD3(5, 0.5, 10), + PCB_MIL_TO_COORD3(2, 0.5, 10)}, + {"mil", PCB_MIL_TO_COORD3(5, 1, 25), + PCB_MIL_TO_COORD3(10, 1, 10), + PCB_MIL_TO_COORD3(5, 0.5, 10), + PCB_MIL_TO_COORD3(2, 0.5, 10)}, + {"in", PCB_MIL_TO_COORD3(5, 1, 25), + PCB_MIL_TO_COORD3(10, 1, 10), + PCB_MIL_TO_COORD3(5, 0.5, 10), + PCB_MIL_TO_COORD3(2, 0.5, 10)}, +}; + +#define N_INCREMENTS (sizeof pcb_increments / sizeof pcb_increments[0]) + +const pcb_unit_t *get_unit_struct(const char *suffix) +{ + 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) + 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_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_list(void) +{ + return pcb_units; +} + +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_increments_t *pcb_get_increments_struct(const char *suffix) +{ + int i; + /* Do lookup */ + for (i = 0; i < N_INCREMENTS; ++i) + if (strcmp(suffix, pcb_increments[i].suffix) == 0) + return &pcb_increments[i]; + return NULL; +} + +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/1.2.7/src/unit.h =================================================================== --- tags/1.2.7/src/unit.h (nonexistent) +++ tags/1.2.7/src/unit.h (revision 13657) @@ -0,0 +1,165 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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]; +}; + +struct pcb_increments_s { + const char *suffix; + /* key g and g value */ + pcb_coord_t grid; + pcb_coord_t grid_min; + pcb_coord_t grid_max; + /* key s and s value */ + pcb_coord_t size; + pcb_coord_t size_min; + pcb_coord_t size_max; + /* key l and l value */ + pcb_coord_t line; + pcb_coord_t line_min; + pcb_coord_t line_max; + /* key k and k value */ + pcb_coord_t clear; + pcb_coord_t clear_min; + pcb_coord_t clear_max; +}; + +typedef struct pcb_unit_s pcb_unit_t; +typedef struct pcb_increments_s pcb_increments_t; +extern pcb_unit_t pcb_units[]; +extern pcb_increments_t pcb_increments[]; + +/* Look up a given suffix in the units array. Pluralized units are supported. */ +const pcb_unit_t *get_unit_struct(const char *suffix); + +/* 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) */ +const pcb_unit_t *get_unit_list(void); +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); + +/* Looks up a given suffix in the increments array. Pluralized units + are not supported. Returns NULL on error. */ +pcb_increments_t *pcb_get_increments_struct(const char *suffix); + +/* 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)) + +#endif Index: tags/1.2.7/src/vtlibrary.c =================================================================== --- tags/1.2.7/src/vtlibrary.c (nonexistent) +++ tags/1.2.7/src/vtlibrary.c (revision 13657) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtlibrary.h" +#include Index: tags/1.2.7/src/vtlibrary.h =================================================================== --- tags/1.2.7/src/vtlibrary.h (nonexistent) +++ tags/1.2.7/src/vtlibrary.h (revision 13657) @@ -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/1.2.7/src/vtonpoint.c =================================================================== --- tags/1.2.7/src/vtonpoint.c (nonexistent) +++ tags/1.2.7/src/vtonpoint.c (revision 13657) @@ -0,0 +1,6 @@ +#define GVT_DONT_UNDEF + +#warning cleanup TODO: this should be replaced with pcb_obj_t + +#include "vtonpoint.h" +#include Index: tags/1.2.7/src/vtonpoint.h =================================================================== --- tags/1.2.7/src/vtonpoint.h (nonexistent) +++ tags/1.2.7/src/vtonpoint.h (revision 13657) @@ -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/1.2.7/src/vtpadstack.c =================================================================== --- tags/1.2.7/src/vtpadstack.c (nonexistent) +++ tags/1.2.7/src/vtpadstack.c (revision 13657) @@ -0,0 +1,7 @@ +/*#define PCB_PADSTACK_STRUCT_ONLY +#include "obj_pstk.h"*/ + +#define GVT_DONT_UNDEF +#include "vtpadstack.h" +#include + Index: tags/1.2.7/src/vtpadstack.h =================================================================== --- tags/1.2.7/src/vtpadstack.h (nonexistent) +++ tags/1.2.7/src/vtpadstack.h (revision 13657) @@ -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/1.2.7/src/vtpadstack_t.c =================================================================== --- tags/1.2.7/src/vtpadstack_t.c (nonexistent) +++ tags/1.2.7/src/vtpadstack_t.c (revision 13657) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtpadstack_t.h" +#include Index: tags/1.2.7/src/vtpadstack_t.h =================================================================== --- tags/1.2.7/src/vtpadstack_t.h (nonexistent) +++ tags/1.2.7/src/vtpadstack_t.h (revision 13657) @@ -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/1.2.7/src/vtroutestyle.c =================================================================== --- tags/1.2.7/src/vtroutestyle.c (nonexistent) +++ tags/1.2.7/src/vtroutestyle.c (revision 13657) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtroutestyle.h" +#include Index: tags/1.2.7/src/vtroutestyle.h =================================================================== --- tags/1.2.7/src/vtroutestyle.h (nonexistent) +++ tags/1.2.7/src/vtroutestyle.h (revision 13657) @@ -0,0 +1,79 @@ +#ifndef PCB_VTROUTESTYLE_H +#define PCB_VTROUTESTYLE_H +#include +#include +#include "unit.h" +#include "attrib.h" + +/* Elem=RouteStyle; init=0 */ + +typedef struct { + pcb_coord_t Thick, /* line thickness */ + Diameter, /* via diameter */ + Hole, /* via drill hole */ + Clearance; /* min. separation from other nets */ + 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/1.2.7/src =================================================================== --- tags/1.2.7/src (nonexistent) +++ tags/1.2.7/src (revision 13657) Property changes on: tags/1.2.7/src ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## + Index: tags/1.2.7/src_3rd/Makefile.conf =================================================================== --- tags/1.2.7/src_3rd/Makefile.conf (nonexistent) +++ tags/1.2.7/src_3rd/Makefile.conf (revision 13657) @@ -0,0 +1 @@ +# placeholder for genvector Index: tags/1.2.7/src_3rd/README =================================================================== --- tags/1.2.7/src_3rd/README (nonexistent) +++ tags/1.2.7/src_3rd/README (revision 13657) @@ -0,0 +1 @@ +3rd party software libs Index: tags/1.2.7/src_3rd/libuhpgl/Makefile =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/Makefile (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/Makefile (revision 13657) @@ -0,0 +1,4 @@ +CFLAGS = -Wall -g -ansi -pedantic + +parse.o: parse.c uhpgl_math.h libuhpgl.h arc_iterate.h + Index: tags/1.2.7/src_3rd/libuhpgl/README =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/README (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/README (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/arc_iterate.h =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/arc_iterate.h (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/arc_iterate.h (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/examples/Makefile =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/Makefile (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/Makefile (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/examples/aa.hpgl =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/aa.hpgl (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/aa.hpgl (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/examples/circ.hpgl =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/circ.hpgl (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/circ.hpgl (revision 13657) @@ -0,0 +1,7 @@ +IN; + +SP1; + +PA50,50; +CI20,10; + Index: tags/1.2.7/src_3rd/libuhpgl/examples/dump_hpgl.c =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/dump_hpgl.c (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/dump_hpgl.c (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/examples/rect.hpgl =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/rect.hpgl (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/rect.hpgl (revision 13657) @@ -0,0 +1,13 @@ +IN; + +SP1; + +PA0,0; + +PD; +PA200,0; +PA200,200; +PA0,200; +PR0,-200; +PU; + Index: tags/1.2.7/src_3rd/libuhpgl/examples/rect_bound.hpgl =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/rect_bound.hpgl (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/rect_bound.hpgl (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/examples/vararg.hpgl =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/examples/vararg.hpgl (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/examples/vararg.hpgl (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/libuhpgl.h =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/libuhpgl.h (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/libuhpgl.h (revision 13657) @@ -0,0 +1,150 @@ +/* + 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] */ + 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/1.2.7/src_3rd/libuhpgl/parse.c =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/parse.c (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/parse.c (revision 13657) @@ -0,0 +1,444 @@ +/* + 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_NUMBERS +} 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('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; + } + 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"); + } + 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': + case ' ': + return 0; + } + + switch(p->state) { + case ST_IDLE: + 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_NUMBERS_OR_END: + if (c == ';') + goto got_end; + /* fall thru: number */ + case ST_NUMBERS: + if ((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"); + } + return error(ctx, "Internal error: broken state machine"); +} Index: tags/1.2.7/src_3rd/libuhpgl/parse.h =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/parse.h (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/parse.h (revision 13657) @@ -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/1.2.7/src_3rd/libuhpgl/uhpgl_math.h =================================================================== --- tags/1.2.7/src_3rd/libuhpgl/uhpgl_math.h (nonexistent) +++ tags/1.2.7/src_3rd/libuhpgl/uhpgl_math.h (revision 13657) @@ -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/1.2.7/src_3rd/qparse/Makefile =================================================================== --- tags/1.2.7/src_3rd/qparse/Makefile (nonexistent) +++ tags/1.2.7/src_3rd/qparse/Makefile (revision 13657) @@ -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/1.2.7/src_3rd/qparse/example.c =================================================================== --- tags/1.2.7/src_3rd/qparse/example.c (nonexistent) +++ tags/1.2.7/src_3rd/qparse/example.c (revision 13657) @@ -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/1.2.7/src_3rd/qparse/qparse.c =================================================================== --- tags/1.2.7/src_3rd/qparse/qparse.c (nonexistent) +++ tags/1.2.7/src_3rd/qparse/qparse.c (revision 13657) @@ -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/1.2.7/src_3rd/qparse/qparse.h =================================================================== --- tags/1.2.7/src_3rd/qparse/qparse.h (nonexistent) +++ tags/1.2.7/src_3rd/qparse/qparse.h (revision 13657) @@ -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/1.2.7/src_3rd =================================================================== --- tags/1.2.7/src_3rd (nonexistent) +++ tags/1.2.7/src_3rd (revision 13657) Property changes on: tags/1.2.7/src_3rd ___________________________________________________________________ Added: svn:externals ## -0,0 +1,11 ## +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 Index: tags/1.2.7/src_plugins/Buildin.tmpasm =================================================================== --- tags/1.2.7/src_plugins/Buildin.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/Buildin.tmpasm (revision 13657) @@ -0,0 +1,27 @@ +# 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 + +@] + +include /local/pcb/tmpasm/common_enabled Index: tags/1.2.7/src_plugins/Common_enabled.tmpasm =================================================================== --- tags/1.2.7/src_plugins/Common_enabled.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/Common_enabled.tmpasm (revision 13657) @@ -0,0 +1,75 @@ +# 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 + +include /local/pcb/tmpasm/plugin_conf +include /local/pcb/tmpasm/plugin_sphash + +append /local/pcb/CLEANFILES ?/local/pcb/mod/CLEANFILES + +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 {} + Index: tags/1.2.7/src_plugins/Disable.tmpasm =================================================================== --- tags/1.2.7/src_plugins/Disable.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/Disable.tmpasm (revision 13657) @@ -0,0 +1,19 @@ +# 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 + + +include /local/pcb/tmpasm/plugin_conf +include /local/pcb/tmpasm/plugin_sphash + +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 {} Index: tags/1.2.7/src_plugins/Plugin.tmpasm =================================================================== --- tags/1.2.7/src_plugins/Plugin.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/Plugin.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/README =================================================================== --- tags/1.2.7/src_plugins/README (nonexistent) +++ tags/1.2.7/src_plugins/README (revision 13657) @@ -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/1.2.7/src_plugins/acompnet/Makefile =================================================================== --- tags/1.2.7/src_plugins/acompnet/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/acompnet/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_acompnet + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/acompnet/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/acompnet/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/acompnet/Plug.tmpasm (revision 13657) @@ -0,0 +1,8 @@ +put /local/pcb/mod {acompnet} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/acompnet/acompnet.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/1.2.7/src_plugins/acompnet/acompnet.c =================================================================== --- tags/1.2.7/src_plugins/acompnet/acompnet.c (nonexistent) +++ tags/1.2.7/src_plugins/acompnet/acompnet.c (revision 13657) @@ -0,0 +1,120 @@ +/* + * 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. + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "layer.h" +#include "layer_ui.h" +/*#include "acompnet_conf.h"*/ +#include "action_helper.h" +#include "hid_actions.h" +#include "plugins.h" +#include "conf.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "error.h" + +#include "obj_all.h" + + +static pcb_layer_t *ly; + +pcb_flag_t flg_mesh_pt; +static void acompnet_mesh_addpt(double x, double y, int score) +{ + x = pcb_round(x); + y = pcb_round(y); + + pcb_line_new(ly, x, y, x, y, conf_core.design.line_thickness, PCB->Bloat, flg_mesh_pt); +} + +static void acompnet_mesh() +{ + double sep = conf_core.design.line_thickness + PCB->Bloat; + int n; + + PCB_LINE_LOOP(CURRENT) { + double 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; + + for(n = 1; n <= 2; n++) { + acompnet_mesh_addpt(x1 - n*vx*sep, y1 - n*vy*sep, n-1); + acompnet_mesh_addpt(x1 - n*vx*sep + nx*sep, y1 - n*vy*sep + ny*sep, n); + acompnet_mesh_addpt(x1 - n*vx*sep - nx*sep, y1 - n*vy*sep - ny*sep, n); + + acompnet_mesh_addpt(x2 + n*vx*sep, y2 + n*vy*sep, n-1); + acompnet_mesh_addpt(x2 + n*vx*sep + nx*sep, y2 + n*vy*sep + ny*sep, n); + acompnet_mesh_addpt(x2 + n*vx*sep - nx*sep, y2 + n*vy*sep - ny*sep, n); + } + } + 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 int pcb_act_acompnet(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + acompnet_mesh(); + return 0; +} + +pcb_hid_action_t acompnet_action_list[] = { + {"acompnet", 0, 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_hid_remove_actions_by_cookie(acompnet_cookie); + pcb_uilayer_free_all_cookie(acompnet_cookie); +} + +#include "dolists.h" +int pplg_init_acompnet(void) +{ + PCB_REGISTER_ACTIONS(acompnet_action_list, acompnet_cookie) + ly = pcb_uilayer_alloc(acompnet_cookie, "autocomp-net", "#c09920"); + + return 0; +} Index: tags/1.2.7/src_plugins/acompnet/acompnet.pup =================================================================== --- tags/1.2.7/src_plugins/acompnet/acompnet.pup (nonexistent) +++ tags/1.2.7/src_plugins/acompnet/acompnet.pup (revision 13657) @@ -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/1.2.7/src_plugins/autocrop/Makefile =================================================================== --- tags/1.2.7/src_plugins/autocrop/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/autocrop/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autocrop + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/autocrop/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/autocrop/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/autocrop/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/autocrop/autocrop.c =================================================================== --- tags/1.2.7/src_plugins/autocrop/autocrop.c (nonexistent) +++ tags/1.2.7/src_plugins/autocrop/autocrop.c (revision 13657) @@ -0,0 +1,267 @@ +/*! + * \file autocrop.c + * + * \brief Autocrop plug-in for PCB. + * Reduce the board dimensions to just enclose the elements. + * + * \author Copyright (C) 2007 Ben Jackson based on teardrops.c by + * Copyright (C) 2006 DJ Delorie + * + * \copyright Licensed under the terms of the GNU General Public + * License, version 2 or later. + * + * Ported to pcb-rnd by Tibor 'Igor2' Palinkas in 2016. + * Copyright (C) 2016..2017 Tibor 'Igor2' Palinkas + * + * From: Ben Jackson + * To: geda-user@moria.seul.org + * Date: Mon, 19 Feb 2007 13:30:58 -0800 + * Subject: Autocrop() plugin for PCB + * + * As a "learn PCB internals" project I've written an Autocrop() plugin. + * It finds the extents of your existing board and resizes the board to + * contain only your parts plus a margin. + * + * There are some issues that I can't resolve from a plugin: + * + *
    + *
  1. Board size has no Undo function, so while Undo will put your objects + * back where they started, the board size has to be replaced manually. + *
  2. There is no 'edge clearance' DRC paramater, so I used 5*line spacing. + *
  3. Moving a layout with lots of objects and polygons is slow due to the + * repeated clearing/unclearing of the polygons as things move. Undo is + * slower than moving because every individual move is drawn (instead of + * one redraw at the end). + *
+ * + * Original source was: http://ad7gd.net/geda/autocrop.c + * + * Run it by typing `:Autocrop()' in the gui, or by binding Autocrop() to a key. + * + * -- + * Ben Jackson AD7GD + * + * http://www.ben.com/ + */ + +#include +#include + +#include "config.h" +#include "board.h" +#include "data.h" +#include "hid.h" +#include "rtree.h" +#include "undo.h" +#include "move.h" +#include "draw.h" +#include "polygon.h" +#include "plugins.h" +#include "obj_all.h" +#include "box.h" +#include "hid_actions.h" + +static const char autocrop_description[] = + "Autocrops the board dimensions to extants + margin"; + +static const char autocrop_syntax[] = + "autocrop()"; + +static void *MyMoveViaLowLevel(pcb_data_t * Data, pcb_pin_t * Via, pcb_coord_t dx, pcb_coord_t dy) +{ + if (Data) { + pcb_poly_restore_to_poly(Data, PCB_TYPE_VIA, Via, Via); + pcb_r_delete_entry(Data->via_tree, (pcb_box_t *) Via); + } + pcb_via_move(Via, dx, dy); + if (Data) { + pcb_r_insert_entry(Data->via_tree, (pcb_box_t *) Via, 0); + pcb_poly_clear_from_poly(Data, PCB_TYPE_VIA, Via, Via); + } + return Via; +} + +static void *MyMoveLineLowLevel(pcb_data_t * Data, pcb_layer_t * Layer, pcb_line_t * Line, pcb_coord_t dx, pcb_coord_t dy) +{ + if (Data) { + pcb_poly_restore_to_poly(Data, PCB_TYPE_LINE, Layer, Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + } + pcb_line_move(Line, dx, dy); + if (Data) { + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + pcb_poly_clear_from_poly(Data, PCB_TYPE_LINE, Layer, Line); + } + return Line; +} + +static void *MyMoveArcLowLevel(pcb_data_t * Data, pcb_layer_t * Layer, pcb_arc_t * Arc, pcb_coord_t dx, pcb_coord_t dy) +{ + if (Data) { + pcb_poly_restore_to_poly(Data, PCB_TYPE_ARC, Layer, Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + } + pcb_arc_move(Arc, dx, dy); + if (Data) { + pcb_r_insert_entry(Layer->arc_tree, (pcb_box_t *) Arc, 0); + pcb_poly_clear_from_poly(Data, PCB_TYPE_ARC, Layer, Arc); + } + return Arc; +} + +static void *Mypcb_poly_move(pcb_data_t * Data, pcb_layer_t * Layer, pcb_poly_t * Polygon, pcb_coord_t dx, pcb_coord_t dy) +{ + if (Data) { + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + } + /* move.c actually only moves points, note no Data/Layer args */ + pcb_poly_move(Polygon, dx, dy); + if (Data) { + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + pcb_poly_init_clip(Data, Layer, Polygon); + } + return Polygon; +} + +static void *MyMoveTextLowLevel(pcb_layer_t * Layer, pcb_text_t * Text, pcb_coord_t dx, pcb_coord_t dy) +{ + if (Layer) + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + pcb_text_move(Text, dx, dy); + if (Layer) + pcb_r_insert_entry(Layer->text_tree, (pcb_box_t *) Text, 0); + return Text; +} + +/*! + * \brief Move everything. + * + * Call our own 'MyMove*LowLevel' where they don't exist in move.c. + * This gets very slow if there are large polygons present, since every + * element move re-clears the poly, followed by the polys moving and + * re-clearing everything again. + */ +static void MoveAll(pcb_coord_t dx, pcb_coord_t dy) +{ + PCB_ELEMENT_LOOP(PCB->Data); + { + pcb_element_move(PCB->Data, element, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_ELEMENT, NULL, NULL, element, dx, dy); + } + PCB_END_LOOP; + PCB_SUBC_LOOP(PCB->Data); + { + pcb_subc_move(subc, dx, dy, pcb_true); + pcb_undo_add_obj_to_move(PCB_TYPE_SUBC, NULL, NULL, subc, dx, dy); + } + PCB_END_LOOP; + PCB_VIA_LOOP(PCB->Data); + { + MyMoveViaLowLevel(PCB->Data, via, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_VIA, NULL, NULL, via, dx, dy); + } + PCB_END_LOOP; + PCB_PADSTACK_LOOP(PCB->Data); + { + pcb_pstk_move(padstack, dx, dy, pcb_true); + pcb_undo_add_obj_to_move(PCB_TYPE_PSTK, NULL, NULL, padstack, dx, dy); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(PCB->Data); + { + MyMoveLineLowLevel(PCB->Data, layer, line, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_LINE, NULL, NULL, line, dx, dy); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(PCB->Data); + { + MyMoveArcLowLevel(PCB->Data, layer, arc, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_ARC, NULL, NULL, arc, dx, dy); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(PCB->Data); + { + MyMoveTextLowLevel(layer, text, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_TEXT, NULL, NULL, text, dx, dy); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(PCB->Data); + { + /* + * XXX MovePolygonLowLevel does not mean "no gui" like + * XXX MoveElementLowLevel, it doesn't even handle layer + * XXX tree activity. + */ + Mypcb_poly_move(PCB->Data, layer, polygon, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_POLY, NULL, NULL, polygon, dx, dy); + } + PCB_ENDALL_LOOP; +} + +static int autocrop(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_coord_t dx, dy, pad; + pcb_box_t tmp, *box; + + box = pcb_data_bbox(&tmp, PCB->Data, pcb_false); /* handy! */ + if (!box || (box->X1 == box->X2 || box->Y1 == box->Y2)) { + /* board would become degenerate */ + return 0; + } + /* + * Now X1/Y1 are the distance to move the left/top edge + * (actually moving all components to the left/up) such that + * the exact edge of the leftmost/topmost component would touch + * the edge. Reduce the move by the edge relief requirement XXX + * and expand the board by the same amount. + */ + pad = PCB->minWid * 5; /* XXX real edge clearance */ + dx = -box->X1 + pad; + dy = -box->Y1 + pad; + box->X2 += pad; + box->Y2 += pad; + /* + * Round move to keep components grid-aligned, then translate the + * upper coordinates into the new space. + */ + dx -= dx % (long) PCB->Grid; + dy -= dy % (long) PCB->Grid; + box->X2 += dx; + box->Y2 += dy; + /* + * Avoid touching any data if there's nothing to do. + */ + if (dx == 0 && dy == 0 && PCB->MaxWidth == box->X2 && PCB->MaxHeight == box->Y2) { + return 0; + } + /* Resize -- XXX cannot be undone */ + PCB->MaxWidth = box->X2; + PCB->MaxHeight = box->Y2; + MoveAll(dx, dy); + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + return 0; +} + +static pcb_hid_action_t autocrop_action_list[] = { + {"autocrop", NULL, autocrop, autocrop_description , autocrop_syntax} +}; + +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_hid_remove_actions_by_cookie(autocrop_cookie); +} + +#include "dolists.h" +int pplg_init_autocrop(void) +{ + PCB_REGISTER_ACTIONS(autocrop_action_list, autocrop_cookie); + return 0; +} Index: tags/1.2.7/src_plugins/autocrop/autocrop.pup =================================================================== --- tags/1.2.7/src_plugins/autocrop/autocrop.pup (nonexistent) +++ tags/1.2.7/src_plugins/autocrop/autocrop.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short crop board to fit objects +$long Reduce the board dimensions to just enclose the elements. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/autoplace/Makefile =================================================================== --- tags/1.2.7/src_plugins/autoplace/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoplace + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/autoplace/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/autoplace/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/autoplace/action.c =================================================================== --- tags/1.2.7/src_plugins/autoplace/action.c (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/action.c (revision 13657) @@ -0,0 +1,79 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "autoplace.h" +#include "plugins.h" +#include "hid_actions.h" +#include "compat_nls.h" +#include "board.h" +#include "event.h" + +static const char autoplace_syntax[] = "AutoPlaceSelected()"; + +static const char autoplace_help[] = "Auto-place selected components."; + +/* %start-doc actions AutoPlaceSelected + +Attempts to re-arrange the selected components such that the nets +connecting them are minimized. Note that you cannot undo this. + +%end-doc */ + +static int pcb_act_AutoPlaceSelected(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_event(PCB_EVENT_BUSY, NULL); + if (pcb_gui->confirm_dialog(_("Auto-placement can NOT be undone.\n" "Do you want to continue anyway?\n"), 0)) { + if (AutoPlaceSelected()) + pcb_board_set_changed_flag(pcb_true); + } + return 0; +} + +static const char *autoplace_cookie = "autoplace plugin"; + +pcb_hid_action_t autoplace_action_list[] = { + {"AutoPlaceSelected", 0, 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_hid_remove_actions_by_cookie(autoplace_cookie); +} + +#include "dolists.h" +int pplg_init_autoplace(void) +{ + PCB_REGISTER_ACTIONS(autoplace_action_list, autoplace_cookie) + return 0; +} Index: tags/1.2.7/src_plugins/autoplace/autoplace.c =================================================================== --- tags/1.2.7/src_plugins/autoplace/autoplace.c (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/autoplace.c (revision 13657) @@ -0,0 +1,988 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * Copyright (C) 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact addresses for paper mail and Email: + * 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 elements. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "board.h" +#include "autoplace.h" +#include "box.h" +#include "compat_misc.h" +#include "compat_nls.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 "rats.h" +#include "remove.h" +#include "rotate.h" +#include "obj_pinvia.h" +#include "obj_rat.h" +#include "obj_term.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) + +static double ComputeCost(pcb_netlist_t *Nets, double T0, double T); + +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 */ +}; + +typedef struct { + pcb_element_t **element; + pcb_cardinal_t elementN; +} ElementPtrListType; + +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; + +#warning cleanup TODO: 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)); + } +} + + +/* --------------------------------------------------------------------------- + * Update the X, Y and group position information stored in the NetList after + * elements have possibly been moved, rotated, flipped, etc. + */ +static void UpdateXY(pcb_netlist_t *Nets) +{ + pcb_layergrp_id_t SLayer = -1, CLayer = -1; + pcb_cardinal_t i, j; + /* find layer groups of the component side and solder side */ + + pcb_layergrp_list(PCB, PCB_LYT_BOTTOM | PCB_LYT_COPPER, &SLayer, 1); + pcb_layergrp_list(PCB, PCB_LYT_TOP | PCB_LYT_COPPER, &CLayer, 1); + + /* update all nets */ + for (i = 0; i < Nets->NetN; i++) { + for (j = 0; j < Nets->Net[i].ConnectionN; j++) { + pcb_connection_t *c = &(Nets->Net[i].Connection[j]); + switch (c->obj->type) { + case PCB_OBJ_PAD: + c->group = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (pcb_element_t *) c->ptr1) + ? SLayer : CLayer; + pcb_obj_center(c->obj, &c->X, &c->Y); + break; + case PCB_OBJ_PIN: + c->group = SLayer; /* any layer will do */ + pcb_obj_center(c->obj, &c->X, &c->Y); + break; + case PCB_OBJ_PSTK: + c->group = SLayer; /* any layer will do */ + c->X = ((pcb_pstk_t *) c->obj)->x; + c->Y = ((pcb_pstk_t *) c->obj)->y; + break; + /* terminals on layer */ + case PCB_OBJ_LINE: + case PCB_OBJ_ARC: + case PCB_OBJ_TEXT: + case PCB_OBJ_POLY: + { + pcb_layer_t *layer = pcb_layer_get_real(c->obj->parent.layer); + if (layer != NULL) + c->group = layer->meta.real.grp; + else + c->group = SLayer; /* any layer will do */ + c->X = (c->obj->BoundingBox.X1 + c->obj->BoundingBox.X2) / 2; + c->Y = (c->obj->BoundingBox.Y1 + c->obj->BoundingBox.Y2) / 2; + } + break; + default: + pcb_message(PCB_MSG_ERROR, "Odd connection type encountered in " "UpdateXY"); + break; + } + } + } +} + +/* --------------------------------------------------------------------------- + * Create a list of selected elements. + */ +static vtp0_t collectSelectedElements() +{ + vtp0_t list; + + vtp0_init(&list); + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + pcb_element_t **epp = (pcb_element_t **)vtp0_alloc_append(&list, 1); + *epp = element; + } + } + 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; +} + +/* --------------------------------------------------------------------------- + * 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(pcb_netlist_t *Nets, 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, j; + 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 */ + /* make sure the NetList have the proper updated X and Y coords */ + UpdateXY(Nets); + /* 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 (i = 0; i < Nets->NetN; i++) { + pcb_net_t *n = &Nets->Net[i]; + if (n->ConnectionN < 2) + continue; /* no cost to go nowhere */ + minx = maxx = n->Connection[0].X; + miny = maxy = n->Connection[0].Y; + thegroup = n->Connection[0].group; + allpads = (n->Connection[0].obj->type == PCB_OBJ_PAD); + allsameside = pcb_true; + for (j = 1; j < n->ConnectionN; j++) { + pcb_connection_t *c = &(n->Connection[j]); + PCB_MAKE_MIN(minx, c->X); + PCB_MAKE_MAX(maxx, c->X); + PCB_MAKE_MIN(miny, c->Y); + PCB_MAKE_MAX(maxy, c->Y); + if (c->obj->type != PCB_OBJ_PAD) + allpads = pcb_false; + if (c->group != thegroup) + allsameside = pcb_false; + } + /* save bounding rectangle */ + { + pcb_box_t *box = pcb_box_new(&bounds); + box->X1 = minx; + box->Y1 = miny; + box->X2 = maxx; + box->Y2 = maxy; + } + /* 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_ELEMENT_LOOP(PCB->Data); + { + pcb_box_list_t *thisside, *otherside; + pcb_box_t *box; + pcb_box_t *lastbox = NULL; + pcb_coord_t thickness, clearance; + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element)) { + thisside = &solderside; + otherside = &componentside; + } + else { + thisside = &componentside; + otherside = &solderside; + } + box = pcb_box_new(thisside); + /* protect against elements with no pins/pads */ + if (pinlist_length(&element->Pin) == 0 && padlist_length(&element->Pad) == 0) + continue; + /* initialize box so that it will take the dimensions of + * the first pin/pad */ + box->X1 = PCB_MAX_COORD; + box->Y1 = PCB_MAX_COORD; + box->X2 = -PCB_MAX_COORD; + box->Y2 = -PCB_MAX_COORD; + PCB_PIN_LOOP(element); + { + thickness = pin->Thickness / 2; + clearance = pin->Clearance * 2; + EXPANDRECTXY(box, + pin->X - (thickness + clearance), + pin->Y - (thickness + clearance), pin->X + (thickness + clearance), pin->Y + (thickness + clearance)); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + thickness = pad->Thickness / 2; + clearance = pad->Clearance * 2; + EXPANDRECTXY(box, + MIN(pad->Point1.X, pad->Point2.X) - (thickness + clearance), + MIN(pad->Point1.Y, pad->Point2.Y) - (thickness + clearance), + MAX(pad->Point1.X, pad->Point2.X) + (thickness + clearance), + MAX(pad->Point1.Y, pad->Point2.Y) + (thickness + clearance)); + } + PCB_END_LOOP; + /* add a box for each pin to the "opposite side": + * surface mount components can't sit on top of pins */ + if (!CostParameter.fast) { + PCB_PIN_LOOP(element); + { + box = pcb_box_new(otherside); + thickness = pin->Thickness / 2; + clearance = pin->Clearance * 2; + /* we ignore clearance here */ + /* (otherwise pins don't fit next to each other) */ + box->X1 = pin->X - thickness; + box->Y1 = pin->Y - thickness; + box->X2 = pin->X + thickness; + box->Y2 = pin->Y + thickness; + /* speed hack! coalesce with last box if we can */ + if (lastbox != NULL && + ((lastbox->X1 == box->X1 && + lastbox->X2 == box->X2 && + MIN(labs(lastbox->Y1 - box->Y2), labs(box->Y1 - lastbox->Y2)) < clearance) || + (lastbox->Y1 == box->Y1 && lastbox->Y2 == box->Y2 && MIN(labs(lastbox->X1 - box->X2), labs(box->X1 - lastbox->X2)) < clearance))) { + EXPANDRECT(lastbox, box); + otherside->BoxN--; + } + else + lastbox = box; + } + PCB_END_LOOP; + } + /* assess out of bounds penalty */ + if (element->VBox.X1 < 0 || element->VBox.Y1 < 0 || element->VBox.X2 > PCB->MaxWidth || element->VBox.Y2 > PCB->MaxHeight) + delta3 += CostParameter.out_of_bounds_penalty; + } + PCB_END_LOOP; + + 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); +#warning subc TODO: 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 */ + +#warning subc TODO: 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; +#warning subc TODO: 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_ELEMENT_LOOP(PCB->Data); + { + boxpp = (struct ebox **) vtp0_alloc_append(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? &seboxes : &ceboxes, 1); + *boxpp = (struct ebox *) malloc(sizeof(**boxpp)); + if (*boxpp == NULL) { + fprintf(stderr, "malloc() failed in ComputeCost\n"); + exit(1); + } + + (*boxpp)->box = element->VBox; + (*boxpp)->comp = (pcb_any_obj_t *)element; + (*boxpp)->refdes = element->Name[0].TextString; + (*boxpp)->rot90 = element->Name[0].Direction; + (*boxpp)->vbox = &element->VBox; + } + PCB_END_LOOP; + 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((const pcb_box_t **) seboxes.array, vtp0_len(&seboxes), 1); + rt_c = pcb_r_create_tree((const pcb_box_t **) ceboxes.array, vtp0_len(&ceboxes), 1); + vtp0_uninit(&seboxes); + vtp0_uninit(&ceboxes); + /* now, for each element, find its neighbor on all four sides */ + delta4 = 0; + for (i = 0; i < 4; i++) { + PCB_ELEMENT_LOOP(PCB->Data); + { + boxp = (struct ebox *)r_find_neighbor(PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? rt_s : rt_c, &element->VBox, dir[i]); + /* score bounding box alignments */ + if (!boxp) + continue; + factor = 1; + if (element->Name[0].TextString && boxp->refdes && 0 == PCB_NSTRCMP(element->Name[0].TextString, boxp->refdes)) { + delta4 += CostParameter.matching_neighbor_bonus; + factor++; + } + if (element->Name[0].Direction == boxp->rot90) + delta4 += factor * CostParameter.oriented_neighbor_bonus; + if (element->VBox.X1 == boxp->vbox->X1 || + element->VBox.X1 == boxp->vbox->X2 || + element->VBox.X2 == boxp->vbox->X1 || + element->VBox.X2 == boxp->vbox->X2 || + element->VBox.Y1 == boxp->vbox->Y1 || + element->VBox.Y1 == boxp->vbox->Y2 || + element->VBox.Y2 == boxp->vbox->Y1 || + element->VBox.Y2 == boxp->vbox->Y2) + delta4 += factor * CostParameter.aligned_neighbor_bonus; + } + PCB_END_LOOP; + + 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_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_ELEMENT_LOOP(PCB->Data); + { + PCB_MAKE_MIN(minX, element->VBox.X1); + PCB_MAKE_MIN(minY, element->VBox.Y1); + PCB_MAKE_MAX(maxX, element->VBox.X2); + PCB_MAKE_MAX(maxY, element->VBox.Y2); + } + PCB_END_LOOP; + 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) +{ + if (obj->type == PCB_OBJ_ELEMENT) + return padlist_length(&(((pcb_element_t *)obj)->Pad)) != 0; + return padstacklist_length(&(((pcb_subc_t *)obj)->data->padstack)) != 0; +} + +static pcb_bool on_bottom(const pcb_any_obj_t *obj) +{ + int onbtm = 0; + + if (obj->type == PCB_OBJ_ELEMENT) + return PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, obj); + + 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 elements (need count/list of selected?) -- + */ +PerturbationType createPerturbation(vtp0_t *selected, double T) +{ + PerturbationType pt = { 0 }; + /* pick element 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 */ + if (pt.comp->type == PCB_OBJ_ELEMENT) { + pcb_element_t *e = (pcb_element_t *)pt.comp; + pt.DX = MAX(pt.DX, -e->VBox.X1); + pt.DX = MIN(pt.DX, PCB->MaxWidth - e->VBox.X2); + pt.DY = MAX(pt.DY, -e->VBox.Y1); + pt.DY = MIN(pt.DY, PCB->MaxHeight - e->VBox.Y2); + } + else { + 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(PerturbationType * pt, pcb_bool undo) +{ + pcb_box_t *bb; + pcb_coord_t bbcx, bbcy; + pcb_element_t *elem = (pcb_element_t *)pt->comp; + pcb_subc_t *subc = (pcb_subc_t *)pt->comp; + /* compute center of element bounding box */ + + if (pt->comp->type == PCB_OBJ_ELEMENT) + bb = &elem->VBox; + else + 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; + } + + if (pt->comp->type == PCB_OBJ_ELEMENT) + pcb_element_move(PCB->Data, elem, DX, DY); + else + 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) { + if (pt->comp->type == PCB_OBJ_ELEMENT) + pcb_element_rotate90(PCB->Data, elem, bbcx, bbcy, b); + else + pcb_subc_rotate90(subc, bbcx, bbcy, b); + } + else { + pcb_coord_t y = bb->Y1; + + if (pt->comp->type == PCB_OBJ_ELEMENT) { + pcb_element_mirror(PCB->Data, elem, 0); + /* mirroring moves the element. move it back. */ + pcb_element_move(PCB->Data, elem, 0, y - elem->VBox.Y1); + } + else { + pcb_subc_change_side(&subc, 0); + 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; + + if (pt->comp->type == PCB_OBJ_ELEMENT) + pcb_element_move(PCB->Data, elem, x2 - x1, y2 - y1); + else + pcb_subc_move(subc, x2 - x1, y2 - y1, 1); + + if (pt->other->type == PCB_OBJ_ELEMENT) + pcb_element_move(PCB->Data, (pcb_element_t *)pt->other, x1 - x2, y1 - y2); + else + pcb_subc_move((pcb_subc_t *)pt->other, x1 - x2, y1 - y2, 1); + + /* then flip both elements 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(&mypt, undo); + mypt.comp = pt->other; + doPerturb(&mypt, undo); + } + /* done */ + return; + } + default: + assert(0); + } +} + +/* --------------------------------------------------------------------------- + * Auto-place selected components. + */ +pcb_bool AutoPlaceSelected(void) +{ + pcb_netlist_t *Nets; + vtp0_t Selected; + PerturbationType pt; + double C0, T0; + pcb_bool changed = pcb_false; + + vtp0_init(&Selected); + + /* (initial netlist processing copied from AddAllRats) */ + /* the netlist library has the text form + * ProcNetlist fills in the Netlist + * structure the way the final routing + * is supposed to look + */ + Nets = pcb_rat_proc_netlist(&(PCB->NetlistLib[PCB_NETLIST_EDITED])); + if (!Nets) { + pcb_message(PCB_MSG_ERROR, _("Can't add rat lines because no netlist is loaded.\n")); + goto done; + } + + Selected = collectSelectedElements(); + if (vtp0_len(&Selected) == 0) { + pcb_message(PCB_MSG_ERROR, _("No elements 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; + C0 = ComputeCost(Nets, Tx, Tx); + for (i = 0; i < TRIALS; i++) { + pt = createPerturbation(&Selected, PCB_INCH_TO_COORD(1)); + doPerturb(&pt, pcb_false); + Cs += fabs(ComputeCost(Nets, Tx, Tx) - C0); + doPerturb(&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(Nets, T0, 5)); + C0 = ComputeCost(Nets, T0, T); + while (1) { + double Cprime; + pt = createPerturbation(&Selected, T); + doPerturb(&pt, pcb_false); + Cprime = ComputeCost(Nets, 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(&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); + /* 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(Nets, T0, T); + } + } + changed = (steps > 0); + } +done: + if (changed) { + pcb_rats_destroy(pcb_false); + pcb_rat_add_all(pcb_false, NULL); + pcb_redraw(); + } + vtp0_uninit(&Selected); + return (changed); +} Index: tags/1.2.7/src_plugins/autoplace/autoplace.h =================================================================== --- tags/1.2.7/src_plugins/autoplace/autoplace.h (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/autoplace.h (revision 13657) @@ -0,0 +1,38 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src_plugins/autoplace/autoplace.pup =================================================================== --- tags/1.2.7/src_plugins/autoplace/autoplace.pup (nonexistent) +++ tags/1.2.7/src_plugins/autoplace/autoplace.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short auto place components +$long Automatically place elements. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/autoroute/Makefile =================================================================== --- tags/1.2.7/src_plugins/autoroute/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoroute + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/autoroute/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/autoroute/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/autoroute/action.c =================================================================== --- tags/1.2.7/src_plugins/autoroute/action.c (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/action.c (revision 13657) @@ -0,0 +1,104 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Harry Eaton, 6697 Buttonhole Ct, Columbia, MD 21044, USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include "config.h" +#include "autoroute.h" +#include "action_helper.h" +#include "plugins.h" +#include "hid_actions.h" +#include "event.h" + +/* action routines for the autorouter + */ + +static const char pcb_acts_AutoRoute[] = "AutoRoute(AllRats|SelectedRats)"; + +static const char pcb_acth_AutoRoute[] = "Auto-route some or all rat lines."; + +/* %start-doc actions AutoRoute + +@table @code + +@item AllRats +Attempt to autoroute all rats. + +@item SelectedRats +Attempt to autoroute the selected rats. + +@end table + +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 line and via +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. + +%end-doc */ + +static int pcb_act_AutoRoute(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function = PCB_ACTION_ARG(0); + pcb_event(PCB_EVENT_BUSY, NULL); + if (function) { /* one parameter */ + if (strcmp(function, "AllRats") == 0) { + if (AutoRoute(pcb_false)) + pcb_board_set_changed_flag(pcb_true); + } + else if ((strcmp(function, "SelectedRats") == 0) || (strcmp(function, "Selected") == 0)) { + if (AutoRoute(pcb_true)) + pcb_board_set_changed_flag(pcb_true); + } + } + return 0; +} + +static const char *autoroute_cookie = "autoroute plugin"; + +pcb_hid_action_t autoroute_action_list[] = { + {"AutoRoute", 0, 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_hid_remove_actions_by_cookie(autoroute_cookie); +} + +#include "dolists.h" +int pplg_init_autoroute(void) +{ + PCB_REGISTER_ACTIONS(autoroute_action_list, autoroute_cookie) + return 0; +} Index: tags/1.2.7/src_plugins/autoroute/autoroute.c =================================================================== --- tags/1.2.7/src_plugins/autoroute/autoroute.c (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/autoroute.c (revision 13657) @@ -0,0 +1,4751 @@ +/* + * COPYRIGHT + * + * 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 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ +/* functions used to autoroute nets. + */ +/* + *------------------------------------------------------------------- + * 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 "mtspace.h" +#include "polygon.h" +#include "rats.h" +#include "remove.h" +#include "obj_pinvia_therm.h" +#include "undo.h" +#include "vector.h" +#include "pcb-printf.h" +#include "layer.h" +#include "compat_nls.h" +#include +#include "layer.h" +#include "obj_all.h" + +#include "obj_line_draw.h" +#include "obj_pinvia_draw.h" + + +/* #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_list { + struct routebox *next, *prev; +} routebox_list; + +typedef enum etype { PAD, PIN, VIA, VIA_SHADOW, LINE, OTHER, EXPANSION_AREA, PLANE, THERMAL } etype; + +typedef struct routebox { + pcb_box_t box, sbox; + union { + pcb_pad_t *pad; + pcb_pin_t *pin; + pcb_pin_t *via; + struct routebox *via_shadow; /* points to the via in r-tree which + * points to the pcb_pin_t in the PCB. */ + pcb_line_t *line; + void *generic; /* 'other' is polygon, arc, text */ + struct routebox *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 same_net, same_subnet, original_subnet, different_net; + union { + pcb_pin_t *via; + pcb_line_t *line; + } livedraw_obj; +} routebox_t; + +typedef struct routedata { + 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 { + 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 { + /* 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; + +struct routeone_state { + /* 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; +}; + + +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(struct routeone_state *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(struct routeone_state *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 struct routebox_list *__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++) { + struct routebox_list *rl = __select_list(r, *p); + rl->prev = rl->next = r; + } +} + +static void MergeNets(routebox_t * a, routebox_t * b, enum boxlist which) +{ + struct routebox_list *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) +{ + struct routebox_list *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 *AddPin(vtp0_t layergroupboxes[], pcb_pin_t *pin, pcb_bool is_via, pcb_route_style_t * style) +{ + routebox_t **rbpp, *lastrb = NULL; + int i, ht; + /* a pin cuts through every layer group */ + for (i = 0; i < pcb_max_group(PCB); i++) { + rbpp = (routebox_t **)vtp0_alloc_append(&layergroupboxes[i], 1); + *rbpp = (routebox_t *) malloc(sizeof(**rbpp)); + memset((void *) *rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = i; + ht = HALF_THICK(MAX(pin->Thickness, pin->DrillingHole)); + init_const_box(*rbpp, + /*X1 */ pin->X - ht, + /*Y1 */ pin->Y - ht, + /*X2 */ pin->X + ht, + /*Y2 */ pin->Y + ht, style->Clearance); + /* set aux. properties */ + if (is_via) { + (*rbpp)->type = VIA; + (*rbpp)->parent.via = pin; + } + else { + (*rbpp)->type = PIN; + (*rbpp)->parent.pin = pin; + } + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = PCB_ANY_DIR; + (*rbpp)->style = style; + (*rbpp)->flags.circular = !PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin); + /* circular lists */ + InitLists(*rbpp); + /* link together */ + if (lastrb) { + MergeNets(*rbpp, lastrb, NET); + MergeNets(*rbpp, lastrb, SUBNET); + MergeNets(*rbpp, lastrb, ORIGINAL); + } + lastrb = *rbpp; + } + return lastrb; +} + +static routebox_t *AddPad(vtp0_t layergroupboxes[], pcb_element_t *element, pcb_pad_t *pad, pcb_route_style_t * style) +{ + pcb_coord_t halfthick; + routebox_t **rbpp; + int layergroup = (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? back : front); + 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 *) malloc(sizeof(**rbpp)); + assert(*rbpp); + memset(*rbpp, 0, sizeof(**rbpp)); + (*rbpp)->group = layergroup; + halfthick = HALF_THICK(pad->Thickness); + init_const_box(*rbpp, + /*X1 */ MIN(pad->Point1.X, pad->Point2.X) - halfthick, + /*Y1 */ MIN(pad->Point1.Y, pad->Point2.Y) - halfthick, + /*X2 */ MAX(pad->Point1.X, pad->Point2.X) + halfthick, + /*Y2 */ MAX(pad->Point1.Y, pad->Point2.Y) + halfthick, + style->Clearance); + /* kludge for non-manhattan pads (which are not allowed at present) */ + if (pad->Point1.X != pad->Point2.X && pad->Point1.Y != pad->Point2.Y) + (*rbpp)->flags.nonstraight = 1; + /* set aux. properties */ + (*rbpp)->type = PAD; + (*rbpp)->parent.pad = pad; + (*rbpp)->flags.fixed = 1; + (*rbpp)->came_from = PCB_ANY_DIR; + (*rbpp)->style = style; + /* circular lists */ + InitLists(*rbpp); + return *rbpp; +} + +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)->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 PAD: + printf("PAD[%s %s] ", rb->parent.pad->Name, rb->parent.pad->Number); + break; + case PIN: + printf("PIN[%s %s] ", rb->parent.pin->Name, rb->parent.pin->Number); + break; + case VIA: + if (!rb->parent.via) + break; + printf("VIA[%s %s] ", rb->parent.via->Name, rb->parent.via->Number); + 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 + +static routedata_t *CreateRouteData() +{ + pcb_netlist_list_t Nets; + 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->ViaOn; + + 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); + + /* 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; + /* add the objects in the netlist first. + * then go and add all other objects that weren't already added + * + * this saves on searching the trees to find the nets + */ + /* use the PCB_FLAG_DRC to mark objects as they are entered */ + pcb_reset_conns(pcb_false); + Nets = pcb_rat_collect_subnets(pcb_false); + { + routebox_t *last_net = NULL; + PCB_NETLIST_LOOP(&Nets); + { + routebox_t *last_in_net = NULL; + PCB_NET_LOOP(netlist); + { + routebox_t *last_in_subnet = NULL; + int j; + + for (j = 0; j < rd->max_styles; j++) + if (net->Style == rd->styles[j]) + break; + PCB_CONNECTION_LOOP(net); + { + routebox_t *rb = NULL; + PCB_FLAG_SET(PCB_FLAG_DRC, (pcb_pin_t *) connection->obj); + if (connection->obj->type == PCB_OBJ_LINE) { + pcb_line_t *line = (pcb_line_t *) connection->obj; + + /* lines are listed at each end, so skip one */ + /* this should probably by a macro named "BUMP_LOOP" */ + n--; + + /* 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, connection->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, connection->group, &fake_line, line, rd->styles[j]); + } + else { + rb = AddLine(layergroupboxes, connection->group, line, line, rd->styles[j]); + } + } + else + switch (connection->obj->type) { + case PCB_OBJ_VOID: break; + case PCB_OBJ_PSTK: +#warning padstack TODO + break; + case PCB_OBJ_PAD: + rb = AddPad(layergroupboxes, (pcb_element_t *) connection->ptr1, (pcb_pad_t *) connection->obj, rd->styles[j]); + break; + case PCB_OBJ_PIN: + rb = AddPin(layergroupboxes, (pcb_pin_t *) connection->obj, pcb_false, rd->styles[j]); + break; + case PCB_OBJ_VIA: + rb = AddPin(layergroupboxes, (pcb_pin_t *) connection->obj, pcb_true, rd->styles[j]); + break; + case PCB_OBJ_POLY: + rb = + AddPolygon(layergroupboxes, + pcb_layer_id(PCB->Data, (pcb_layer_t *) connection->ptr1), + (struct pcb_poly_s *) connection->obj, rd->styles[j]); + break; + case PCB_OBJ_POINT: + case PCB_OBJ_LINE: + case PCB_OBJ_TEXT: + case PCB_OBJ_ARC: + case PCB_OBJ_RAT: + case PCB_OBJ_ELEMENT: + case PCB_OBJ_SUBC: + case PCB_OBJ_NET: + case PCB_OBJ_LAYER: + case PCB_OBJ_ELINE: + case PCB_OBJ_EARC: + case PCB_OBJ_ETEXT: + break; /* don't care about these */ + } + 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); + } + PCB_END_LOOP; + } + PCB_END_LOOP; + if (last_net && last_in_net) + MergeNets(last_net, last_in_net, DIFFERENT_NET); + last_net = last_in_net; + } + PCB_END_LOOP; + rd->first_net = last_net; + } + pcb_netlist_list_free(&Nets); + + /* 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; + } + + /* add pins and pads of elements */ + PCB_PIN_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, pin)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pin); + else + AddPin(layergroupboxes, pin, pcb_false, rd->styles[rd->max_styles]); + } + PCB_ENDALL_LOOP; + PCB_PAD_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, pad)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pad); + else + AddPad(layergroupboxes, element, pad, rd->styles[rd->max_styles]); + } + PCB_ENDALL_LOOP; + /* add all vias */ + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, via)) + PCB_FLAG_CLEAR(PCB_FLAG_DRC, via); + else + AddPin(layergroupboxes, via, pcb_true, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + + for (i = 0; i < pcb_max_layer; i++) { + pcb_layergrp_id_t layergroup; + + if (!(pcb_layer_flags(PCB, i) & PCB_LYT_COPPER)) + continue; + + layergroup = pcb_layer_get_group(PCB, i); + + /* add all (non-rat) lines */ + PCB_LINE_LOOP(LAYER_PTR(i)); + { + 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(LAYER_PTR(i)); + { + 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(LAYER_PTR(i)); + { + AddText(layergroupboxes, layergroup, text, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + /* add all arcs */ + PCB_ARC_LOOP(LAYER_PTR(i)); + { + AddArc(layergroupboxes, layergroup, arc, rd->styles[rd->max_styles]); + } + PCB_END_LOOP; + } + + /* 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((const pcb_box_t **) layergroupboxes[i].array, vtp0_len(&layergroupboxes[i]), 1); + } + + 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_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; + } + else if (target->type == PAD) { + if (labs(target->parent.pad->Point1.X - nextpoint->X) < labs(target->parent.pad->Point2.X - nextpoint->X)) + nextpoint->X = target->parent.pad->Point1.X; + else + nextpoint->X = target->parent.pad->Point2.X; + if (labs(target->parent.pad->Point1.Y - nextpoint->Y) < labs(target->parent.pad->Point2.Y - nextpoint->Y)) + nextpoint->Y = target->parent.pad->Point1.Y; + else + nextpoint->Y = target->parent.pad->Point2.Y; + return pcb_true; + } + else { + 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, Trace_Cap); + 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_TYPE_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_TYPE_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_TYPE_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, Trace_Cap); + 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 */ + assert(relax_edge_requirements ? pcb_box_intersect(&rb->sbox, &parent->sbox) + : share_edge(&rb->sbox, &parent->sbox)); + 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, + struct routeone_state *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, 1); + 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, 1); + 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(struct routeone_state * 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 != PIN && rbox->type != VIA && rbox->type != VIA_SHADOW) + 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 PIN: + sq = pcb_shrink_box(&ti->query, rbox->parent.pin->Thickness); + if (!pcb_box_intersect(&sb, &sq)) + return PCB_R_DIR_NOT_FOUND; + sb.X1 = rbox->parent.pin->X; + sb.Y1 = rbox->parent.pin->Y; + break; + case VIA: + if (rbox->flags.fixed) { + sq = pcb_shrink_box(&ti->query, rbox->parent.via->Thickness); + sb.X1 = rbox->parent.pin->X; + sb.Y1 = rbox->parent.pin->Y; + } + else { + sq = pcb_shrink_box(&ti->query, rbox->style->Diameter); + sb.X1 = PCB_BOX_CENTER_X(sb); + sb.Y1 = PCB_BOX_CENTER_Y(sb); + } + if (!pcb_box_intersect(&sb, &sq)) + return PCB_R_DIR_NOT_FOUND; + break; + 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, 1); + 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_pin_t *live_via = NULL; + + if (conf_core.editor.live_routing) { + live_via = pcb_via_new(PCB->Data, X, Y, radius * 2, + 2 * AutoRouteParameters.style->Clearance, 0, AutoRouteParameters.style->Hole, NULL, pcb_flag_make(0)); + if (live_via != NULL) + pcb_via_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, 1); + 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->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, 1); + + 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 == PIN); + 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(struct routeone_state *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(struct routeone_state *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(struct routeone_state *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(struct routeone_state *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, struct routeone_state *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); +} + +struct routeone_status { + pcb_bool found_route; + int route_had_conflicts; + pcb_cost_t best_route_cost; + pcb_bool net_completely_routed; +}; + + +static struct routeone_status RouteOne(routedata_t * rd, routebox_t * from, routebox_t * to, int max_edges) +{ + struct routeone_status 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; + + struct routeone_state 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((const pcb_box_t **) target_list, i, 0); + 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, 1); + 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, 1); + 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(rd->layergrouptree[rb->group], &rb->box); + } + 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_TYPE_LINE, layer, rb->livedraw_obj.line, NULL); + rb->livedraw_obj.line = NULL; + } + if (rb->type == VIA && rb->livedraw_obj.via) { + pcb_via_invalidate_erase(rb->livedraw_obj.via); + pcb_destroy_object(PCB->Data, PCB_TYPE_VIA, 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; + struct routeone_status 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(rd->layergrouptree[p->group], &p->box); +#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 == PAD ? 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_gui->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_pin_t *pin; + pcb_coord_t X, Y; + jmp_buf env; +}; + +static pcb_r_dir_t fpin_rect(const pcb_box_t * b, void *cl) +{ + pcb_pin_t *pin = (pcb_pin_t *) b; + struct fpin_info *info = (struct fpin_info *) cl; + if (pin->X == info->X && pin->Y == info->Y) { + info->pin = (pcb_pin_t *) b; + longjmp(info->env, 1); + } + return PCB_R_DIR_NOT_FOUND; +} + +static int FindPin(const pcb_box_t * box, pcb_pin_t ** pin) +{ + struct fpin_info info; + + info.pin = NULL; + info.X = box->X1; + info.Y = box->Y1; + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->pin_tree, box, NULL, fpin_rect, &info, NULL); + else { + *pin = info.pin; + return PCB_TYPE_PIN; + } + if (setjmp(info.env) == 0) + pcb_r_search(PCB->Data->via_tree, box, NULL, fpin_rect, &info, NULL); + else { + *pin = info.pin; + return PCB_TYPE_VIA; + } + *pin = NULL; + return PCB_TYPE_NONE; +} + + +/* 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, b.X1, b.Y1, b.X2, b.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_TYPE_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(b.X1 + radius == b.X2 - radius); + assert(b.Y1 + radius == b.Y2 - radius); + pp->parent.via = + pcb_via_new(PCB->Data, b.X1 + radius, + b.Y1 + radius, + pp->style->Diameter, 2 * pp->style->Clearance, 0, pp->style->Hole, NULL, pcb_flag_make(PCB_FLAG_AUTO)); + assert(pp->parent.via); + if (pp->parent.via) { + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, 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_pin_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->Element ? pin->Element : pin, pin, pin, pcb_false); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_VIA, LAYER_PTR(p->layer), pin); + pcb_undo_add_obj_to_flag(pin); + PCB_FLAG_THERM_ASSIGN(p->layer, PCB->ThermStyle, pin); + pcb_undo_add_obj_to_clear_poly(type, pin->Element ? pin->Element : pin, pin, pin, pcb_true); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_VIA, 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, Round_Cap); + } +#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); + pcb_save_find_flag(PCB_FLAG_DRC); + 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_gui->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_rat_add_all(pcb_false /*all rats */ , NULL); + pcb_undo_restore_serial(); + + pcb_undo_inc_serial(); + + pcb_redraw(); + } + pcb_restore_find_flag(); +#if defined (ROUTE_DEBUG) + aabort = 0; +#endif + return (changed); +} Index: tags/1.2.7/src_plugins/autoroute/autoroute.h =================================================================== --- tags/1.2.7/src_plugins/autoroute/autoroute.h (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/autoroute.h (revision 13657) @@ -0,0 +1,39 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src_plugins/autoroute/autoroute.pup =================================================================== --- tags/1.2.7/src_plugins/autoroute/autoroute.pup (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/autoroute.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short the original autorouter +$long Automatically route selected or all rats. This is the original autorouter. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/autoroute/mtspace.c =================================================================== --- tags/1.2.7/src_plugins/autoroute/mtspace.c (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/mtspace.c (revision 13657) @@ -0,0 +1,504 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "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(NULL, 0, 0); + mtspace->etree = pcb_r_create_tree(NULL, 0, 0); + mtspace->otree = pcb_r_create_tree(NULL, 0, 0); + /* done! */ + return mtspace; +} + +/* destroy an "empty space" representation. */ +void mtspace_destroy(mtspace_t ** mtspacep) +{ + assert(mtspacep); + 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(info->tree, b); + 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, 1); +} + +/* 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; + assert(pcb_box_intersect(qc->cbox, &mtsb->box)); + /* 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/1.2.7/src_plugins/autoroute/mtspace.h =================================================================== --- tags/1.2.7/src_plugins/autoroute/mtspace.h (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/mtspace.h (revision 13657) @@ -0,0 +1,74 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src_plugins/autoroute/vector.c =================================================================== --- tags/1.2.7/src_plugins/autoroute/vector.c (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/vector.c (revision 13657) @@ -0,0 +1,199 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src_plugins/autoroute/vector.h =================================================================== --- tags/1.2.7/src_plugins/autoroute/vector.h (nonexistent) +++ tags/1.2.7/src_plugins/autoroute/vector.h (revision 13657) @@ -0,0 +1,72 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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/1.2.7/src_plugins/boardflip/Makefile =================================================================== --- tags/1.2.7/src_plugins/boardflip/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/boardflip/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_boardflip + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/boardflip/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/boardflip/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/boardflip/Plug.tmpasm (revision 13657) @@ -0,0 +1,8 @@ +put /local/pcb/mod {boardflip} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/boardflip/boardflip.o @] + +switch /local/pcb/boardflip/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/1.2.7/src_plugins/boardflip/boardflip.c =================================================================== --- tags/1.2.7/src_plugins/boardflip/boardflip.c (nonexistent) +++ tags/1.2.7/src_plugins/boardflip/boardflip.c (revision 13657) @@ -0,0 +1,277 @@ +/*! + * \file boardflip.c + * + * \brief BoardFlip plug-in for PCB. + * + * \author Copyright (C) 2008 DJ Delorie + * + * \copyright Licensed under the terms of the GNU General Public + * License, version 2 or later. + * + * Ported to pcb-rnd by Tibor 'Igor2' Palinkas in 2016; generalized in 2017. + * + * Original source was: http://www.delorie.com/pcb/boardflip.c + * + * Usage: Boardflip() + * + * All objects on the board are up-down flipped. + * + * Command line board flipping: + * + * pcb --action-string "BoardFlip() SaveTo(LayoutAs,$OUTFILE) Quit()" $INFILE + * + * To flip the board physically, use BoardFlip(sides) + * + */ + +#include +#include + +#include "config.h" +#include "board.h" +#include "rats.h" +#include "polygon.h" +#include "data.h" +#include "hid.h" +#include "rtree.h" +#include "undo.h" +#include "plugins.h" +#include "obj_all.h" +#include "hid_actions.h" +#include "compat_misc.h" +#include "boardflip.h" + + +/* Things that need to be flipped: + + lines + text + polygons + arcs + vias + elements + elementlines + elementarcs + pins + pads + rats +*/ + +#define XFLIP(v) (v) = ((flip_x ? -(v) : (v)) + xo) +#define YFLIP(v) (v) = ((flip_y ? -(v) : (v)) + yo) +#define AFLIP(a) (a) = aflip((a), flip_x, flip_y) +#define NEG(a) (a) = -(a) +#define ONLY1 ((flip_x || flip_y) && !(flip_x && flip_y)) + +static double aflip(double a, pcb_bool flip_x, pcb_bool flip_y) +{ + if (flip_x) { + while(a > 360.0) a -= 360.0; + while(a < 0.0) a += 360.0; + + if ((0.0 <= a) && (a <= 90.0)) a = (90.0 - a) + 90.0; + else if ((0 < 90.0) && (a <= 180.0)) a = 90.0 - (a - 90.0); + else if ((0 < 180.0) && (a <= 270.0)) a = 270.0 + (270.0 - a); + else if ((0 < 270.0) && (a <= 360.0)) a = 270.0 - (a - 270.0); + + while(a > 360.0) a -= 360.0; + while(a < 0.0) a += 360.0; + } + if (flip_y) + a = -a; + return a; +} + +void pcb_flip_data(pcb_data_t *data, pcb_bool flip_x, pcb_bool flip_y, pcb_coord_t xo, pcb_coord_t yo, pcb_bool et_swap_sides) +{ + LAYER_LOOP(data, pcb_max_layer); + { + PCB_LINE_LOOP(layer); + { + pcb_poly_restore_to_poly(data, PCB_TYPE_LINE, layer, line); + pcb_r_delete_entry(layer->line_tree, (pcb_box_t *)line); + XFLIP(line->Point1.X); + XFLIP(line->Point2.X); + YFLIP(line->Point1.Y); + YFLIP(line->Point2.Y); + pcb_line_bbox(line); + pcb_r_insert_entry(layer->line_tree, (pcb_box_t *)line, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_LINE, layer, line); + } + PCB_END_LOOP; + PCB_TEXT_LOOP(layer); + { + pcb_poly_restore_to_poly(data, PCB_TYPE_TEXT, layer, text); + pcb_r_delete_entry(layer->text_tree, (pcb_box_t *)text); + XFLIP(text->X); + YFLIP(text->Y); + if (et_swap_sides && ONLY1) + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, text); + pcb_text_bbox(pcb_font(PCB, text->fid, 1), text); + pcb_r_insert_entry(layer->text_tree, (pcb_box_t *)text, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_TEXT, layer, text); + } + PCB_END_LOOP; + PCB_POLY_LOOP(layer); + { + int i, j; + pcb_r_delete_entry(layer->polygon_tree, (pcb_box_t *)polygon); + PCB_POLY_POINT_LOOP(polygon); + { + XFLIP(point->X); + YFLIP(point->Y); + } + PCB_END_LOOP; + if (ONLY1) { + i = 0; + j = polygon->PointN - 1; + while (i < j) { + pcb_point_t p = polygon->Points[i]; + polygon->Points[i] = polygon->Points[j]; + polygon->Points[j] = p; + i++; + j--; + } + } + pcb_poly_bbox(polygon); + pcb_r_insert_entry(layer->polygon_tree, (pcb_box_t *)polygon, 0); + pcb_poly_init_clip(data, layer, polygon); + } + PCB_END_LOOP; + PCB_ARC_LOOP(layer); + { + pcb_poly_restore_to_poly(data, PCB_TYPE_ARC, layer, arc); + pcb_r_delete_entry(layer->arc_tree, (pcb_box_t *)arc); + XFLIP(arc->X); + YFLIP(arc->Y); + AFLIP(arc->StartAngle); + if (ONLY1) + NEG(arc->Delta); + pcb_arc_bbox(arc); + pcb_r_insert_entry(layer->arc_tree, (pcb_box_t *)arc, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_ARC, layer, arc); + } + PCB_END_LOOP; + } + PCB_END_LOOP; + PCB_VIA_LOOP(data); + { + pcb_r_delete_entry(data->via_tree, (pcb_box_t *)via); + pcb_poly_restore_to_poly(data, PCB_TYPE_VIA, via, via); + XFLIP(via->X); + YFLIP(via->Y); + pcb_pin_bbox(via); + pcb_r_insert_entry(data->via_tree, (pcb_box_t *) via, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_VIA, via, via); + } + PCB_END_LOOP; +#warning subc TODO + PCB_ELEMENT_LOOP(data); + { + XFLIP(element->MarkX); + YFLIP(element->MarkY); + if (et_swap_sides && ONLY1) + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, element); + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_r_delete_entry(data->name_tree[n], (pcb_box_t *)text); + XFLIP(text->X); + YFLIP(text->Y); + if (et_swap_sides) + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, text); + pcb_r_insert_entry(data->name_tree[n], (pcb_box_t *)text, 0); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + XFLIP(line->Point1.X); + XFLIP(line->Point2.X); + YFLIP(line->Point1.Y); + YFLIP(line->Point2.Y); + } + PCB_END_LOOP; + PCB_ELEMENT_ARC_LOOP(element); + { + XFLIP(arc->X); + YFLIP(arc->Y); + AFLIP(arc->StartAngle); + if (ONLY1) + NEG(arc->Delta); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + pcb_r_delete_entry(data->pin_tree, (pcb_box_t *)pin); + pcb_poly_restore_to_poly(data, PCB_TYPE_PIN, element, pin); + XFLIP(pin->X); + YFLIP(pin->Y); + pcb_pin_bbox(pin); + pcb_r_insert_entry(data->pin_tree, (pcb_box_t *)pin, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_PIN, element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_r_delete_entry(data->pad_tree, (pcb_box_t *)pad); + pcb_poly_restore_to_poly(data, PCB_TYPE_PAD, element, pad); + XFLIP(pad->Point1.X); + XFLIP(pad->Point2.X); + YFLIP(pad->Point1.Y); + YFLIP(pad->Point2.Y); + if (et_swap_sides && ONLY1) + PCB_FLAG_TOGGLE(PCB_FLAG_ONSOLDER, pad); + pcb_pad_bbox(pad); + pcb_r_insert_entry(data->pad_tree, (pcb_box_t *)pad, 0); + pcb_poly_clear_from_poly(data, PCB_TYPE_PAD, element, pad); + } + PCB_END_LOOP; + pcb_element_bbox(data, element, pcb_font(PCB, 0, 1)); /* also does the rtree administration */ + } + PCB_END_LOOP; + PCB_RAT_LOOP(data); + { + pcb_r_delete_entry(data->rat_tree, (pcb_box_t *)line); + XFLIP(line->Point1.X); + XFLIP(line->Point2.X); + YFLIP(line->Point1.Y); + YFLIP(line->Point2.Y); + pcb_r_insert_entry(data->rat_tree, (pcb_box_t *)line, 0); + } + PCB_END_LOOP; +} + +static int boardflip(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int h = PCB->MaxHeight; + int sides = 0; + + if (argc > 0 && pcb_strcasecmp(argv[0], "sides") == 0) + sides = 1; + printf("argc %d argv %s sides %d\n", argc, argc > 0 ? argv[0] : "", sides); + pcb_flip_data(PCB->Data, pcb_false, pcb_true, 0, h, sides); + return 0; +} + + +static pcb_hid_action_t boardflip_action_list[] = { + {"BoardFlip", NULL, boardflip, NULL, NULL} +}; + +char *boardflip_cookie = "boardflip plugin"; + +PCB_REGISTER_ACTIONS(boardflip_action_list, boardflip_cookie) + +int pplg_check_ver_boardflip(int ver_needed) { return 0; } + +void pplg_uninit_boardflip(void) +{ + pcb_hid_remove_actions_by_cookie(boardflip_cookie); +} + +#include "dolists.h" +int pplg_init_boardflip(void) +{ + PCB_REGISTER_ACTIONS(boardflip_action_list, boardflip_cookie); + return 0; +} + Index: tags/1.2.7/src_plugins/boardflip/boardflip.h =================================================================== --- tags/1.2.7/src_plugins/boardflip/boardflip.h (nonexistent) +++ tags/1.2.7/src_plugins/boardflip/boardflip.h (revision 13657) @@ -0,0 +1,6 @@ +#include "data.h" +#include "unit.h" + +/* et_swap_sides: toggle elements/text solder side flag */ +void pcb_flip_data(pcb_data_t *data, pcb_bool flip_x, pcb_bool flip_y, pcb_coord_t xo, pcb_coord_t yo, pcb_bool et_swap_sides); + Index: tags/1.2.7/src_plugins/boardflip/boardflip.pup =================================================================== --- tags/1.2.7/src_plugins/boardflip/boardflip.pup (nonexistent) +++ tags/1.2.7/src_plugins/boardflip/boardflip.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short flip board objects +$long All objects on the board are up-down flipped. +$lstate doesn't update rtrees +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/diag/Makefile =================================================================== --- tags/1.2.7/src_plugins/diag/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/diag/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_diag + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/diag/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/diag/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/diag/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/diag/diag.c =================================================================== --- tags/1.2.7/src_plugins/diag/diag.c (nonexistent) +++ tags/1.2.7/src_plugins/diag/diag.c (revision 13657) @@ -0,0 +1,373 @@ +/* + * 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. + * + */ + +#include "config.h" +#include "board.h" +#include "data.h" +#include "flag_str.h" +#include "layer.h" +#include "diag_conf.h" +#include "action_helper.h" +#include "hid_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" + +conf_diag_t conf_diag; + +static const char dump_conf_syntax[] = + "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 dump_conf_help[] = "Perform various operations on the configuration tree."; + +extern lht_doc_t *conf_root[]; +static int pcb_act_DumpConf(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *cmd = argc > 0 ? argv[0] : NULL; + + if (PCB_NSTRCMP(cmd, "native") == 0) { + int verbose; + const char *prefix = ""; + if (argc > 1) + verbose = atoi(argv[1]); + if (argc > 2) + prefix = argv[2]; + conf_dump(stdout, prefix, verbose, NULL); + } + + else if (PCB_NSTRCMP(cmd, "lihata") == 0) { + conf_role_t role; + const char *prefix = ""; + if (argc <= 1) { + pcb_message(PCB_MSG_ERROR, "conf(dumplht) needs a role"); + return 1; + } + role = conf_role_parse(argv[1]); + if (role == CFR_invalid) { + pcb_message(PCB_MSG_ERROR, "Invalid role: '%s'", argv[1]); + return 1; + } + if (argc > 2) + prefix = argv[2]; + if (conf_root[role] != NULL) + lht_dom_export(conf_root[role]->root, stdout, prefix); + else + printf("%s \n", prefix); + } + + else { + pcb_message(PCB_MSG_ERROR, "Invalid conf command '%s'\n", argv[0]); + return 1; + } + return 0; +} + +static const char eval_conf_syntax[] = + "EvalConf(path) - evaluate a config path in different config sources to figure how it ended up in the native database\n" + ; + +static const char eval_conf_help[] = "Perform various operations on the configuration tree."; + +static int pcb_act_EvalConf(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *path = argc > 0 ? argv[0] : NULL; + conf_native_t *nat; + int role; + + if (path == NULL) { + pcb_message(PCB_MSG_ERROR, "EvalConf needs a path\n"); + return 1; + } + + nat = conf_get_field(path); + if (nat == NULL) { + pcb_message(PCB_MSG_ERROR, "EvalConf: invalid path %s - no such config setting\n", path); + return 1; + } + + 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); + + return 0; +} + +static const char dump_layers_syntax[] = + "dumplayers()\n" + ; + +static const char dump_layers_help[] = "Print info about each layer"; + +extern lht_doc_t *conf_root[]; +static int pcb_act_DumpLayers(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int 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 */ + + + 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); + } + } + + 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 int pcb_act_DumpFonts(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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"); + 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 int pcb_act_DumpUndo(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + printf("Undo:\n"); + undo_dump(); + return 0; +} +#endif + +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 int pcb_act_integrity(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_check_integrity(PCB); + 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 dumpflags_syntax[] = "dumpflags([fmt])\n"; +static const char dumpflags_help[] = "dump flags, optionally using the format string provided by the user"; +static int pcb_act_dumpflags(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int n; + const char *default_fmt = "%m (%M %N) for %t:\n %H\n"; + const char *fmt; + + if (argc > 0) + fmt = argv[0]; + else + fmt = default_fmt; + + 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); + } + + 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 d1_syntax[] = "d1()\n"; +static const char d1_help[] = "debug action for development"; +static int pcb_act_d1(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + printf("D1!\n"); + return 0; +} + +#define PCB_FORCECOLOR_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_SUBC | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLY | PCB_TYPE_SUBC_PART | PCB_TYPE_SUBC | PCB_TYPE_RATLINE) + +static const char forcecolor_syntax[] = "forcecolor(#RRGGBB)\n"; +static const char forcecolor_help[] = "change selected element's color to #RRGGBB, reset if does not start with '#'"; +static int pcb_act_forcecolor(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int type; + void *ptr1, *ptr2, *ptr3; + + const char *new_color = PCB_ACTION_ARG(0); + + pcb_gui->get_coords("Click on object to change", &x, &y); + + if ((type = pcb_search_screen(x, y, PCB_FORCECOLOR_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE){ + strncpy(((pcb_any_obj_t *)ptr2)->override_color, new_color, sizeof(((pcb_any_obj_t *)ptr2)->override_color)-1); + } + return 0; +} + +pcb_hid_action_t diag_action_list[] = { + {"dumpconf", 0, pcb_act_DumpConf, + dump_conf_help, dump_conf_syntax}, + {"dumplayers", 0, pcb_act_DumpLayers, + dump_layers_help, dump_layers_syntax}, + {"dumpfonts", 0, pcb_act_DumpFonts, + dump_fonts_help, dump_fonts_syntax}, +#ifndef NDEBUG + {"dumpundo", 0, pcb_act_DumpUndo, + dump_undo_help, dump_undo_syntax}, +#endif + {"EvalConf", 0, pcb_act_EvalConf, + eval_conf_help, eval_conf_syntax}, + {"d1", 0, pcb_act_d1, + d1_help, d1_syntax}, + {"integrity", 0, pcb_act_integrity, + integrity_help, integrity_syntax}, + {"dumpflags", 0, pcb_act_dumpflags, + dumpflags_help, dumpflags_syntax}, + {"forcecolor", 0, pcb_act_forcecolor, + forcecolor_help, forcecolor_syntax} +}; + +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_hid_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) +{ +#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/1.2.7/src_plugins/diag/diag.pup =================================================================== --- tags/1.2.7/src_plugins/diag/diag.pup (nonexistent) +++ tags/1.2.7/src_plugins/diag/diag.pup (revision 13657) @@ -0,0 +1,6 @@ +$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. +$state works +default disable +autoload 1 Index: tags/1.2.7/src_plugins/diag/diag_conf.c =================================================================== --- tags/1.2.7/src_plugins/diag/diag_conf.c (nonexistent) +++ tags/1.2.7/src_plugins/diag/diag_conf.c (revision 13657) @@ -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. + * + */ + +#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/1.2.7/src_plugins/diag/diag_conf.h =================================================================== --- tags/1.2.7/src_plugins/diag/diag_conf.h (nonexistent) +++ tags/1.2.7/src_plugins/diag/diag_conf.h (revision 13657) @@ -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/1.2.7/src_plugins/diag/integrity.c =================================================================== --- tags/1.2.7/src_plugins/diag/integrity.c (nonexistent) +++ tags/1.2.7/src_plugins/diag/integrity.c (revision 13657) @@ -0,0 +1,266 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "error.h" +#include "undo.h" + +#define CHK "Broken integrity: " + +#define check_parent(name, obj, pt, prnt) \ + do { \ + if (obj->parent_type != pt) \ + pcb_message(PCB_MSG_ERROR, CHK "%s " name " %ld parent type proken (%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 proken (%p != %p)\n", whose, obj->ID, obj->parent.any, prnt); \ + } 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 chk_layer_attr(ly) \ + do { \ + if (!(ly)->is_bound) { \ + if (((ly)->meta.real.Attributes.Number > 0) && ((ly)->meta.real.Attributes.List == NULL)) \ + pcb_message(PCB_MSG_ERROR, CHK "%s layer %s broken empty attribute list\n", whose, (ly)->name); \ + } \ + } 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_element(const char *whose, pcb_element_t *elem) +{ + int n; + pcb_pin_t *pin; + pcb_pad_t *pad; + pcb_line_t *lin; + pcb_arc_t *arc; + + for(pin = pinlist_first(&elem->Pin); pin != NULL; pin = pinlist_next(pin)) + check_parent("pin", pin, PCB_PARENT_ELEMENT, elem); + + for(pad = padlist_first(&elem->Pad); pad != NULL; pad = padlist_next(pad)) + check_parent("pad", pad, PCB_PARENT_ELEMENT, elem); + + for(lin = linelist_first(&elem->Line); lin != NULL; lin = linelist_next(lin)) + check_parent("line", lin, PCB_PARENT_ELEMENT, elem); + + for(arc = arclist_first(&elem->Arc); arc != NULL; arc = arclist_next(arc)) + check_parent("arc", arc, PCB_PARENT_ELEMENT, elem); + + for(n = 1; n < PCB_MAX_ELEMENTNAMES; n++) { + check_field_eq("element name", elem, &elem->Name[n], &elem->Name[0], X, "%mm"); + check_field_eq("element name", elem, &elem->Name[n], &elem->Name[0], Y, "%mm"); + check_field_eq("element name", elem, &elem->Name[n], &elem->Name[0], Direction, "%d"); + check_field_eq("element name", elem, &elem->Name[n], &elem->Name[0], fid, "%d"); + } +} + +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 ((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 ((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_pin_t *via; + + chk_layers("subc", subc->data, PCB_PARENT_SUBC, subc, 0); + chk_subc_cache(subc); + + /* check term chaches */ + for(via = pinlist_first(&subc->data->Via); via != NULL; via = pinlist_next(via)) + chk_term("via", (pcb_any_obj_t *)via); + + 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; + + if (data->parent_type != pt) + pcb_message(PCB_MSG_ERROR, CHK "%s data: parent type proken (%d != %d)\n", whose, data->parent_type, pt); + else if (data->parent.any != parent) + pcb_message(PCB_MSG_ERROR, CHK "%s data: parent proken (%p != %p)\n", whose, data->parent, parent); + + + for(n = 0; n < pcb_max_layer; n++) { + pcb_line_t *lin; + pcb_text_t *txt; + pcb_arc_t *arc; + pcb_poly_t *poly; + + /* check layers */ + if (data->Layer[n].parent != data) + pcb_message(PCB_MSG_ERROR, CHK "%s layer %ld/%s parent proken (%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); + chk_layer_attr(&data->Layer[n]); + + /* 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]); + 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]); + 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]); + 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]); + chk_attr("arc", arc); + } + } + + /* check global objects */ + { + pcb_pin_t *via; + pcb_element_t *elem; + pcb_subc_t *subc; + + for(via = pinlist_first(&data->Via); via != NULL; via = pinlist_next(via)) { + check_parent("via", via, PCB_PARENT_DATA, data); + chk_attr("via", via); + } + + for(elem = elementlist_first(&data->Element); elem != NULL; elem = elementlist_next(elem)) { + check_parent("element", elem, PCB_PARENT_DATA, data); + chk_element(whose, elem); + chk_attr("element", elem); + } + + for(subc = pcb_subclist_first(&data->subc); subc != NULL; subc = pcb_subclist_next(subc)) { + check_parent("subc", subc, PCB_PARENT_DATA, data); + chk_subc(whose, subc); + chk_attr("subc", subc); + } + } +#warning subc TODO: check buffers: parents +} + +void pcb_check_integrity(pcb_board_t *pcb) +{ + int n; + 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/1.2.7/src_plugins/diag/integrity.h =================================================================== --- tags/1.2.7/src_plugins/diag/integrity.h (nonexistent) +++ tags/1.2.7/src_plugins/diag/integrity.h (revision 13657) @@ -0,0 +1,3 @@ +#include "board.h" +void pcb_check_integrity(pcb_board_t *pcb); + Index: tags/1.2.7/src_plugins/dialogs/Makefile =================================================================== --- tags/1.2.7/src_plugins/dialogs/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_dialogs + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/dialogs/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/dialogs/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/Plug.tmpasm (revision 13657) @@ -0,0 +1,10 @@ +put /local/pcb/mod {dialogs} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/dialogs/dialogs.o +@] + +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/1.2.7/src_plugins/dialogs/dialogs.c =================================================================== --- tags/1.2.7/src_plugins/dialogs/dialogs.c (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dialogs.c (revision 13657) @@ -0,0 +1,66 @@ +/* + * 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. + * + */ + +#include "config.h" +#include "hid.h" +#include "hid_attrib.h" +#include "hid_actions.h" +#include "hid_dad.h" +#include "action_helper.h" + +/* include them all for static inlines */ +#include "dlg_test.c" +#include "dlg_layer_binding.c" +#include "dlg_flag_edit.c" +#include "dlg_padstack.c" + +pcb_hid_action_t dialogs_action_list[] = { + {"dlg_test", 0, pcb_act_dlg_test, + dlg_test_help, dlg_test_syntax}, + {"LayerBinding", 0, pcb_act_LayerBinding, + pcb_acth_LayerBinding, pcb_acts_LayerBinding}, + {"FlagEdit", 0, pcb_act_FlagEdit, + pcb_acth_FlagEdit, pcb_acts_FlagEdit}, + {"PadstackEdit", 0, pcb_act_PadstackEdit, + pcb_acth_PadstackEdit, pcb_acts_PadstackEdit} +}; + +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_hid_remove_actions_by_cookie(dialogs_cookie); +} + +#include "dolists.h" +int pplg_init_dialogs(void) +{ + PCB_REGISTER_ACTIONS(dialogs_action_list, dialogs_cookie) + return 0; +} Index: tags/1.2.7/src_plugins/dialogs/dialogs.pup =================================================================== --- tags/1.2.7/src_plugins/dialogs/dialogs.pup (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dialogs.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short HID-independent GUI dialogs +$long Interactive core functionality: HID-independent GUI dialogs (enabled by GUI HIDs) +$state works +default disable +autoload 1 Index: tags/1.2.7/src_plugins/dialogs/dlg_flag_edit.c =================================================================== --- tags/1.2.7/src_plugins/dialogs/dlg_flag_edit.c (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dlg_flag_edit.c (revision 13657) @@ -0,0 +1,133 @@ +/* + * 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. + * + */ + +#include "flag.h" +#include "flag_str.h" +#include "change.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_TYPE_PSTK | PCB_TYPE_VIA | PCB_TYPE_ELEMENT | PCB_TYPE_LINE | PCB_TYPE_POLY | \ + PCB_TYPE_TEXT | PCB_TYPE_SUBC | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_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(); +} + + + +static const char pcb_acts_FlagEdit[] = "FlagEdit(object)\n"; +static const char pcb_acth_FlagEdit[] = "Change the layer binding."; +static int pcb_act_FlagEdit(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + fe_ctx_t ctx; + pcb_hid_attr_val_t val; + int type; + + memset(&ctx, 0, sizeof(ctx)); + + if ((argc == 0) || (pcb_strcasecmp(argv[0], "object") == 0)) { + void *ptr1, *ptr2, *ptr3; + pcb_gui->get_coords("Click on object to change flags of", &x, &y); + type = pcb_search_screen(x, y, PCB_FLAGEDIT_TYPES, &ptr1, &ptr2, &ptr3); + ctx.ptr1 = ptr1; + ctx.obj = (pcb_any_obj_t *)ptr2; + ctx.obj_type = (type & 0xFFFF) | (type & PCB_TYPE_PSTK); + } + else + PCB_ACT_FAIL(FlagEdit); + + if (ctx.obj_type != 0) { /* interactive mode */ + int n; + char tmp[128]; + PCB_DAD_DECL(dlg); + + ctx.pcb = PCB; + ctx.len = 0; + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_LABEL); + + sprintf(tmp, "Object flags of %x #%ld\n", 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_BOOL(dlg, pcb_object_flagbits[n].name); + 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(dlg, 1); + ctx.len++; + } + } + PCB_DAD_END(dlg); + + ctx.attrs = dlg; + + PCB_DAD_NEW(dlg, "flag_edit", "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); + } + + return 0; +} Index: tags/1.2.7/src_plugins/dialogs/dlg_layer_binding.c =================================================================== --- tags/1.2.7/src_plugins/dialogs/dlg_layer_binding.c (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dlg_layer_binding.c (revision 13657) @@ -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. + * + */ + +#include "board.h" +#include "data.h" +#include "const.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "obj_subc.h" +#include "search.h" + +static const char *lb_comp[] = { "+manual", "-manual", "+auto", "-auto", NULL }; +static const char *lb_types[] = { "UNKNOWN", "paste", "mask", "silk", "copper", "outline", "virtual", NULL }; +static const char *lb_side[] = { "top", "bottom", NULL }; + +typedef struct { + int name, comp, type, offs, from, side, 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; + +static void set_ly_type(void *hid_ctx, int wid, pcb_layer_type_t type) +{ + int val; + + val = 0; + if (type & PCB_LYT_PASTE) val = 1; + else if (type & PCB_LYT_MASK) val = 2; + else if (type & PCB_LYT_SILK) val = 3; + else if (type & PCB_LYT_COPPER) val = 4; + else if (type & PCB_LYT_OUTLINE) val = 5; + else if (type & PCB_LYT_VIRTUAL) val = 6; + + PCB_DAD_SET_VALUE(hid_ctx, wid, int_value, val); +} + +static void get_ly_type(int combo_type, int combo_side, int dlg_offs, pcb_layer_type_t *type, int *offs) +{ + /* 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_OUTLINE; break; + case 6: *type |= PCB_LYT_VIRTUAL; break; + } + + /* 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)) + +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_OUTLINE); + 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)); + + PCB_DAD_SET_VALUE(hid_ctx, w->comp, int_value, layer->comb); + + set_ly_type(hid_ctx, w->type, layer->meta.bound.type); + + /* side & offset */ + PCB_DAD_SET_VALUE(hid_ctx, w->side, int_value, !!(layer->meta.bound.type & PCB_LYT_BOTTOM)); + + 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); + + enable = !(layer->meta.bound.type & PCB_LYT_VIRTUAL) && !(layer->meta.bound.type & PCB_LYT_OUTLINE); + pcb_gui->attr_dlg_widget_state(hid_ctx, w->side, 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); + } + + 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); + } +} + + +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 */ +} + +static const char pcb_acts_LayerBinding[] = "LayerBinding(object)\nLayerBinding(selected)\nLayerBinding(buffer)\n"; +static const char pcb_acth_LayerBinding[] = "Change the layer binding."; +static int pcb_act_LayerBinding(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + lb_ctx_t ctx; + int num_copper; + pcb_hid_attr_val_t val; + + memset(&ctx, 0, sizeof(ctx)); + + if ((argc == 0) || (pcb_strcasecmp(argv[0], "object") == 0)) { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_gui->get_coords("Click on object to change size of", &x, &y); + type = pcb_search_screen(x, y, PCB_TYPE_SUBC, &ptr1, &ptr2, &ptr3); + if (type != PCB_TYPE_SUBC) { + pcb_message(PCB_MSG_ERROR, "No subc under the cursor\n"); + return -1; + } + ctx.subc = ptr2; + ctx.data = ctx.subc->data; + } + else if (pcb_strcasecmp(argv[0], "selected") == 0) { +#warning subc TODO + pcb_message(PCB_MSG_ERROR, "TODO\n"); + return 1; + } + else if (pcb_strcasecmp(argv[0], "buffer") == 0) { + ctx.data = PCB_PASTEBUFFER->Data; + } + else + PCB_ACT_FAIL(LayerBinding); + + { /* interactive mode */ + int n; + + 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_TABLE(dlg, 2); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_SCROLL); + 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, lb_comp); /* coposite */ + w->comp = PCB_DAD_CURRENT(dlg); + PCB_DAD_ENUM(dlg, 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, lb_side); + w->side = 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); + + ctx.attrs = dlg; + + PCB_DAD_NEW(dlg, "layer_binding", "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); + } + + return 0; +} Index: tags/1.2.7/src_plugins/dialogs/dlg_padstack.c =================================================================== --- tags/1.2.7/src_plugins/dialogs/dlg_padstack.c (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dlg_padstack.c (revision 13657) @@ -0,0 +1,588 @@ +/* + * 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. + * + */ + +#include "obj_pstk.h" +#include "obj_pstk_inlines.h" + +typedef struct pse_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; +} pse_proto_layer_t; + +static const pse_proto_layer_t pse_layer[] = { + {"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_MIL_TO_COORD(4)}, + {"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_MIL_TO_COORD(4)}, + {"bottom paste", PCB_LYT_BOTTOM | PCB_LYT_PASTE, PCB_LYC_AUTO, {4,-1}, 0} +}; +#define pse_num_layers (sizeof(pse_layer) / sizeof(pse_layer[0])) + +typedef struct pse_s { + pcb_hid_attribute_t *attrs; + pcb_board_t *pcb; + pcb_pstk_t *ps; + int tab; + + /* widget IDs */ + int tab_instance, tab_prototype; + int but_instance, but_prototype; + int proto_id, clearance, rot, xmirror, smirror; + int proto_shape[pse_num_layers]; + int proto_info[pse_num_layers]; + int proto_change[pse_num_layers]; + int hole_header; + int hdia, hplated; + int htop_val, htop_text, htop_layer; + int hbot_val, hbot_text, hbot_layer; + + /* 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; + int copy_do, copy_from; + int shrink, amount, grow; +} pse_t; + +static void pse_tab_update(void *hid_ctx, pse_t *pse) +{ + switch(pse->tab) { + case 0: + pcb_gui->attr_dlg_widget_hide(hid_ctx, pse->tab_instance, pcb_false); + pcb_gui->attr_dlg_widget_hide(hid_ctx, pse->tab_prototype, pcb_true); + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->but_instance, pcb_false); + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->but_prototype, pcb_true); + break; + case 1: + pcb_gui->attr_dlg_widget_hide(hid_ctx, pse->tab_instance, pcb_true); + pcb_gui->attr_dlg_widget_hide(hid_ctx, pse->tab_prototype, pcb_false); + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->but_instance, pcb_true); + pcb_gui->attr_dlg_widget_state(hid_ctx, pse->but_prototype, pcb_false); + break; + } +} + +/* 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; + 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; + + 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 */ + sprintf(tmp, "#%ld, %d", (long int)pse->ps->proto, pse->ps->protoi); + 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 */ + for(n = 0; n < pse_num_layers; n++) { + pcb_pstk_shape_t *shape = pcb_pstk_shape(pse->ps, pse_layer[n].mask, pse_layer[n].comb); + if (shape != NULL) { + switch(shape->shape) { + case PCB_PSSH_CIRC: + PCB_DAD_SET_VALUE(hid_ctx, pse->proto_shape[n], str_value, "circle"); + pcb_snprintf(tmp, sizeof(tmp), "dia=$%mm at $%mm;$%mm", shape->data.circ.dia, shape->data.circ.x, shape->data.circ.y); + 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=%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); + } + 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, ""); + } + } + + /* proto - hole */ + 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_DAD_SET_VALUE(hid_ctx, pse->hole_header, str_value, s); + + 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_tab_ps(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pse->tab = 0; + pse_tab_update(hid_ctx, pse); +} + +static void pse_tab_proto(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr) +{ + pse_t *pse = caller_data; + pse->tab = 1; + pse_tab_update(hid_ctx, pse); +} + +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--; + + 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--; + + 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, pse_layer[pse->editing_shape].mask, pse_layer[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, 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 = pcb_pstk_get_shape_idx(ts, pse_layer[pse->editing_shape].mask, pse_layer[pse->editing_shape].comb); + char src_shape_names[128]; + char *end = src_shape_names; + + for(n = 0; n < 2; n++) { + int from = pse_layer[pse->editing_shape].auto_from[n]; + if (from < 0) + continue; + src_idx = pcb_pstk_get_shape_idx(ts, pse_layer[from].mask, pse_layer[from].comb); + if (src_idx >= 0) + break; + strcpy(end, pse_layer[from].name); + end += strlen(pse_layer[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, pse_layer[pse->editing_shape].auto_bloat, pse_layer[pse->editing_shape].mask, pse_layer[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, 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 = pcb_pstk_get_shape_idx(ts, pse_layer[pse->editing_shape].mask, pse_layer[pse->editing_shape].comb); + int src_idx = pcb_pstk_get_shape_idx(ts, pse_layer[from].mask, pse_layer[from].comb); + + if (src_idx < 0) { + pcb_message(PCB_MSG_ERROR, "Can't copy shape: source shape (%s) is empty\n", pse_layer[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, pse_layer[pse->editing_shape].auto_bloat, pse_layer[pse->editing_shape].mask, pse_layer[pse->editing_shape].comb); + + pse_ps2dlg(pse->parent_hid_ctx, 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, pse_layer[pse->editing_shape].mask, pse_layer[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", pse_layer[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); + + pse_ps2dlg(pse->parent_hid_ctx, 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[pse_num_layers+1]; + PCB_DAD_DECL(dlg); + + pse->parent_hid_ctx = hid_ctx; + + for(n = 0; n < pse_num_layers; n++) + copy_from_names[n] = pse_layer[n].name; + copy_from_names[n] = NULL; + + pse->editing_shape = -1; + for(n = 0; n < pse_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, "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_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_ENUM(dlg, copy_from_names); /* coposite */ + pse->copy_from = PCB_DAD_CURRENT(dlg); + PCB_DAD_HELP(dlg, "Select the source layer type for manual shape copy"); + 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_END(dlg); + + PCB_DAD_NEW(dlg, "dlg_padstack_edit_shape", "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); +} + +static const char pcb_acts_PadstackEdit[] = "PadstackEdit(object)\n"; +static const char pcb_acth_PadstackEdit[] = "interactive pad stack editor"; +static int pcb_act_PadstackEdit(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int n; + pse_t pse; + PCB_DAD_DECL(dlg); + + memset(&pse, 0, sizeof(pse)); + + if ((argc == 0) || (pcb_strcasecmp(argv[0], "object") == 0)) { + void *ptr1, *ptr2 = NULL, *ptr3; + long type; + pcb_gui->get_coords("Click on a padstack to edit", &x, &y); + type = pcb_search_screen(x, y, PCB_TYPE_PSTK | PCB_TYPE_SUBC_PART | PCB_LOOSE_SUBC, &ptr1, &ptr2, &ptr3); + if (type != PCB_TYPE_PSTK) { + pcb_message(PCB_MSG_ERROR, "Need a padstack.\n"); + return 1; + } + 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; + + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_BUTTON(dlg, "this instance"); + pse.but_instance = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_tab_ps); + PCB_DAD_HELP(dlg, "Change the properties of\nthis one padstack instance"); + PCB_DAD_BUTTON(dlg, "prototype"); + pse.but_prototype = PCB_DAD_CURRENT(dlg); + PCB_DAD_CHANGE_CB(dlg, pse_tab_proto); + PCB_DAD_HELP(dlg, "Change the properties of\nthe padstack prototype used by\nthis padstack\n(affects all padstacks using the same prototype)"); + PCB_DAD_END(dlg); + + /* this instance */ + PCB_DAD_BEGIN_VBOX(dlg); + pse.tab_instance = PCB_DAD_CURRENT(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + PCB_DAD_BEGIN_HBOX(dlg); + PCB_DAD_LABEL(dlg, "prototype"); + PCB_DAD_BUTTON(dlg, "#5"); + pse.proto_id = PCB_DAD_CURRENT(dlg); + PCB_DAD_HELP(dlg, "Padstack prototype ID\n(click to use a different prototype)"); + 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, 1); + 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); + + /* prototype */ + PCB_DAD_BEGIN_VBOX(dlg); + pse.tab_prototype = PCB_DAD_CURRENT(dlg); + PCB_DAD_BEGIN_VBOX(dlg); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + PCB_DAD_LABEL(dlg, "Pad geometry per layer type:"); + PCB_DAD_BEGIN_TABLE(dlg, 4); + PCB_DAD_COMPFLAG(dlg, PCB_HATF_FRAME); + for(n = 0; n < pse_num_layers; n++) { + PCB_DAD_LABEL(dlg, pse_layer[n].name); + 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_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, 1); + 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, "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 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: 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 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: 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); + PCB_DAD_END(dlg); + + PCB_DAD_NEW(dlg, "dlg_padstack_edit", "Edit padstack", &pse, pcb_true, NULL); + pse.attrs = dlg; + pse_tab_update(dlg_hid_ctx, &pse); + pse_ps2dlg(dlg_hid_ctx, &pse); + PCB_DAD_RUN(dlg); + + PCB_DAD_FREE(dlg); + return 0; +} + Index: tags/1.2.7/src_plugins/dialogs/dlg_test.c =================================================================== --- tags/1.2.7/src_plugins/dialogs/dlg_test.c (nonexistent) +++ tags/1.2.7/src_plugins/dialogs/dlg_test.c (revision 13657) @@ -0,0 +1,72 @@ +/* + * 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. + * + */ + +static const char dlg_test_syntax[] = "dlg_test()\n"; +static const char dlg_test_help[] = "test the attribute dialog"; +static void pcb_act_attr_chg(void *hid_ctx, void *caller_data, pcb_hid_attribute_t *attr); +static int attr_idx, attr_idx2; +static int pcb_act_dlg_test(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *vals[] = { "foo", "bar", "baz", NULL }; + + PCB_DAD_DECL(foo); + PCB_DAD_BEGIN_VBOX(foo); + PCB_DAD_LABEL(foo, "text1"); + PCB_DAD_BEGIN_TABLE(foo, 3); + PCB_DAD_LABEL(foo, "text2a"); + PCB_DAD_LABEL(foo, "text2b"); + PCB_DAD_LABEL(foo, "text2c"); + PCB_DAD_LABEL(foo, "text2d"); + PCB_DAD_END(foo); + PCB_DAD_LABEL(foo, "text3"); + + PCB_DAD_ENUM(foo, vals); + PCB_DAD_CHANGE_CB(foo, pcb_act_attr_chg); + attr_idx = PCB_DAD_CURRENT(foo); + PCB_DAD_INTEGER(foo, "text2e"); + PCB_DAD_MINVAL(foo, 1); + PCB_DAD_MAXVAL(foo, 10); + PCB_DAD_DEFAULT(foo, 3); + PCB_DAD_CHANGE_CB(foo, pcb_act_attr_chg); + attr_idx2 = PCB_DAD_CURRENT(foo); + PCB_DAD_BUTTON(foo, "update!"); + PCB_DAD_CHANGE_CB(foo, pcb_act_attr_chg); + PCB_DAD_END(foo); + + PCB_DAD_AUTORUN(foo, "dlg_test", "attribute dialog test", NULL); + + PCB_DAD_FREE(foo); + 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); +} Index: tags/1.2.7/src_plugins/distalign/Makefile =================================================================== --- tags/1.2.7/src_plugins/distalign/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/distalign/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distalign + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/distalign/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/distalign/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/distalign/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/distalign/distalign.c =================================================================== --- tags/1.2.7/src_plugins/distalign/distalign.c (nonexistent) +++ tags/1.2.7/src_plugins/distalign/distalign.c (revision 13657) @@ -0,0 +1,644 @@ +/*! + * \file distalign.c + * + * \brief distalign plug-in for PCB. + * Functions to distribute (evenly spread out) and align PCB elements. + * + * \author Copyright (C) 2007 Ben Jackson + * + * \copyright Licensed under the terms of the GNU General Public + * License, version 2 or later. + * + * Ported to pcb-rnd by Tibor 'Igor2' Palinkas in 2016. + * + * 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. + * + * Original source was: http://ad7gd.net/geda/distalign.c + * + * [*] 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/ + */ + +#include +#include + +#include "board.h" +#include "config.h" +#include "data.h" +#include "hid.h" +#include "rtree.h" +#include "undo.h" +#include "rats.h" +#include "error.h" +#include "move.h" +#include "draw.h" +#include "plugins.h" +#include "action_helper.h" +#include "hid_actions.h" +#include "compat_misc.h" + +#define ARG(n) (argc > (n) ? argv[n] : 0) + +static const char align_syntax[] = + "Align(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])"; + +static const char distribute_syntax[] = + "Distribute(X/Y, [Lefts/Rights/Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])"; + +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_element_t *element, int point) \ +{ \ + switch (point) { \ + case K_Marks: \ + return element->Mark ## DIR; \ + case K_Lefts: \ + case K_Tops: \ + return element->BoundingBox.DIR ## 1; \ + case K_Rights: \ + case K_Bottoms: \ + return element->BoundingBox.DIR ## 2; \ + case K_Centers: \ + case K_Gaps: \ + return (element->BoundingBox.DIR ## 1 + \ + element->BoundingBox.DIR ## 2) / 2; \ + } \ + return 0; \ +} + +COORD(X) + COORD(Y) + +/* return the element coordinate associated with the given internal point */ + static pcb_coord_t coord(pcb_element_t * element, int dir, int point) +{ + if (dir == K_X) + return coordX(element, point); + else + return coordY(element, point); +} + +static struct element_by_pos { + pcb_element_t *element; + pcb_coord_t pos; + pcb_coord_t width; +} *elements_by_pos; + +static int nelements_by_pos; + +static int cmp_ebp(const void *a, const void *b) +{ + const struct element_by_pos *ea = a; + const struct element_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" 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_elements_by_pos(int op, int dir, int point) +{ + int nsel = 0; + + if (nelements_by_pos) + return nelements_by_pos; + if (op == K_align) + dir = dir == K_X ? K_Y : K_X; /* see above */ + PCB_ELEMENT_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + continue; + nsel++; + } + PCB_END_LOOP; + if (!nsel) + return 0; + elements_by_pos = malloc(nsel * sizeof(*elements_by_pos)); + nelements_by_pos = nsel; + nsel = 0; + PCB_ELEMENT_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + continue; + elements_by_pos[nsel].element = element; + elements_by_pos[nsel++].pos = coord(element, dir, point); + } + PCB_END_LOOP; + qsort(elements_by_pos, nelements_by_pos, sizeof(*elements_by_pos), cmp_ebp); + return nelements_by_pos; +} + +static void free_elements_by_pos(void) +{ + if (nelements_by_pos) { + free(elements_by_pos); + elements_by_pos = NULL; + nelements_by_pos = 0; + } +} + +/*! + * \brief Find the reference coordinate from the specified points of all + * selected elements. + */ +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 elements */ + nsel = 0; + q = 0; + PCB_ELEMENT_LOOP(PCB->Data); + { + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + continue; + q += coord(element, 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_elements_by_pos(op, dir, point)) { + q = 0; + break; + } + if (reference == K_First) { + q = coord(elements_by_pos[0].element, dir, point); + } + else { + q = coord(elements_by_pos[nelements_by_pos - 1].element, dir, point); + } + break; + } + return q; +} + +/*! + * Align(X, [Lefts/Rights/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]])\n + * Align(Y, [Tops/Bottoms/Centers/Marks, [First/Last/pcb_crosshair/Average[, Gridless]]]) + * + * X or Y - Select which axis will move, other is untouched. \n + * Lefts, Rights, \n + * Tops, Bottoms, \n + * Centers, Marks - Pick alignment point within each element. \n + * First, Last, \n + * pcb_crosshair, \n + * Average - Alignment reference, First=Topmost/Leftmost, \n + * Last=Bottommost/Rightmost, Average or pcb_crosshair point \n + * Gridless - Do not force results to align to prevailing grid. \n + * + * Defaults are Marks, First. + */ +static int align(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int dir; + int point; + int reference; + int gridless; + pcb_coord_t q; + int changed = 0; + + if (argc < 1 || argc > 4) { + PCB_AFAIL(align); + } + /* parse direction arg */ + switch ((dir = keyword(ARG(0)))) { + case K_X: + case K_Y: + break; + default: + PCB_AFAIL(align); + } + /* parse point (within each element) which will be aligned */ + switch ((point = keyword(ARG(1)))) { + case K_Centers: + case K_Marks: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_AFAIL(align); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_AFAIL(align); + } + break; + case K_none: + point = K_Marks; /* default value */ + break; + default: + PCB_AFAIL(align); + } + /* parse reference which will determine alignment coordinates */ + switch ((reference = keyword(ARG(2)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + reference = K_First; /* default value */ + break; + default: + PCB_AFAIL(align); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(ARG(3))) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_AFAIL(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 elements to the new coordinate */ + PCB_ELEMENT_LOOP(PCB->Data); + { + pcb_coord_t p, dp, dx, dy; + + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + continue; + /* find delta from reference point to reference point */ + p = coord(element, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + if (!gridless) { + dp -= (coord(element, 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_element_move(PCB->Data, element, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_ELEMENT, NULL, NULL, element, dx, dy); + changed = 1; + } + } + PCB_END_LOOP; + if (changed) { + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + } + free_elements_by_pos(); + return 0; +} + +/*! + * Distribute(X, [Lefts/Rights/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) \n + * Distribute(Y, [Tops/Bottoms/Centers/Marks/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) \n + * \n + * As with align, plus: \n + * \n + * Gaps - Make gaps even rather than spreading points evenly. \n + * First, Last, \n + * pcb_crosshair - Two arguments specifying both ends of the distribution, + * they can't both be the same. \n + * \n + * Defaults are Marks, First, Last \n + * \n + * Distributed elements always retain the same relative order they had + * before they were distributed. \n + */ +static int distribute(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int dir; + int point; + int refa, refb; + int gridless; + pcb_coord_t s, e, slack; + int divisor; + int changed = 0; + int i; + + if (argc < 1 || argc == 3 || argc > 4) { + PCB_AFAIL(distribute); + } + /* parse direction arg */ + switch ((dir = keyword(ARG(0)))) { + case K_X: + case K_Y: + break; + default: + PCB_AFAIL(distribute); + } + /* parse point (within each element) which will be distributed */ + switch ((point = keyword(ARG(1)))) { + case K_Centers: + case K_Marks: + case K_Gaps: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_AFAIL(distribute); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_AFAIL(distribute); + } + break; + case K_none: + point = K_Marks; /* default value */ + break; + default: + PCB_AFAIL(distribute); + } + /* parse reference which will determine first distribution coordinate */ + switch ((refa = keyword(ARG(2)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refa = K_First; /* default value */ + break; + default: + PCB_AFAIL(distribute); + } + /* parse reference which will determine final distribution coordinate */ + switch ((refb = keyword(ARG(3)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refb = K_Last; /* default value */ + break; + default: + PCB_AFAIL(distribute); + } + if (refa == refb) { + PCB_AFAIL(distribute); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(ARG(4))) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_AFAIL(distribute); + } + /* build list of elements in orthogonal axis order */ + sort_elements_by_pos(K_distribute, dir, point); + /* find the endpoints given the above options */ + s = reference_coord(K_distribute, x, y, dir, point, refa); + e = reference_coord(K_distribute, x, y, dir, point, refb); + slack = e - s; + /* use this divisor to calculate spacing (for 1 elt, avoid 1/0) */ + divisor = (nelements_by_pos > 1) ? (nelements_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 < nelements_by_pos; ++i) { + pcb_element_t *element = elements_by_pos[i].element; + /* coord doesn't care if I mix Lefts/Tops */ + w = elements_by_pos[i].width = coord(element, dir, K_Rights) - coord(element, dir, K_Lefts); + /* Gaps distribution is on centers, so half of + * first and last element don't count */ + if (i == 0 || i == nelements_by_pos - 1) { + w /= 2; + } + slack -= w; + } + /* slack could be negative */ + } + /* move all selected elements to the new coordinate */ + for (i = 0; i < nelements_by_pos; ++i) { + pcb_element_t *element = elements_by_pos[i].element; + pcb_coord_t p, q, dp, dx, dy; + + /* find reference point for this element */ + q = s + slack * i / divisor; + /* find delta from reference point to reference point */ + p = coord(element, dir, point); + dp = q - p; + /* ...but if we're gridful, keep the mark on the grid */ + if (!gridless) { + dp -= (coord(element, 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_element_move(PCB->Data, element, dx, dy); + pcb_undo_add_obj_to_move(PCB_TYPE_ELEMENT, NULL, NULL, element, dx, dy); + changed = 1; + } + /* in gaps mode, accumulate part widths */ + if (point == K_Gaps) { + /* move remaining half of our element */ + s += elements_by_pos[i].width / 2; + /* move half of next element */ + if (i < nelements_by_pos - 1) + s += elements_by_pos[i + 1].width / 2; + } + } + if (changed) { + pcb_undo_inc_serial(); + pcb_redraw(); + pcb_board_set_changed_flag(1); + } + free_elements_by_pos(); + return 0; +} + +static pcb_hid_action_t distalign_action_list[] = { + {"distribute", NULL, distribute, "Distribute Elements", distribute_syntax}, + {"align", NULL, align, "Align Elements", align_syntax} +}; + +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_hid_remove_actions_by_cookie(distalign_cookie); +} + +#include "dolists.h" +int pplg_init_distalign(void) +{ + PCB_REGISTER_ACTIONS(distalign_action_list, distalign_cookie); + return 0; +} + + Index: tags/1.2.7/src_plugins/distalign/distalign.pup =================================================================== --- tags/1.2.7/src_plugins/distalign/distalign.pup (nonexistent) +++ tags/1.2.7/src_plugins/distalign/distalign.pup (revision 13657) @@ -0,0 +1,6 @@ +$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. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/distaligntext/Makefile =================================================================== --- tags/1.2.7/src_plugins/distaligntext/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/distaligntext/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distaligntext + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/distaligntext/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/distaligntext/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/distaligntext/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/distaligntext/distaligntext.c =================================================================== --- tags/1.2.7/src_plugins/distaligntext/distaligntext.c (nonexistent) +++ tags/1.2.7/src_plugins/distaligntext/distaligntext.c (revision 13657) @@ -0,0 +1,639 @@ +/*! + * \file distaligntext.c + * + * \brief distaligntext plug-in for PCB. + * + * \author Copyright (C) 2012 Dan White + * Functions to distribute (evenly spread out) and align PCB text. + * + * \copyright 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. + * + * + * 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 "rats.h" +#include "error.h" +#include "move.h" +#include "draw.h" +#include "plugins.h" +#include "action_helper.h" +#include "hid_actions.h" +#include "conf_core.h" +#include "box.h" +#include "compat_misc.h" + +#define ARG(n) (argc > (n) ? argv[n] : 0) + +static const char aligntext_syntax[] = + "AlignText(X/Y, [Lefts/Rights/Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])"; + +static const char distributetext_syntax[] = + "DistributeText(Y, [Lefts/Rights/Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]])"; + +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; + int type; +} *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_ELEMENT_LOOP(PCB->Data); + { + pcb_text_t *text; + text = &(element)->Name[PCB_ELEMNAME_IDX_VISIBLE()]; + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + continue; + nsel++; + } + 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_ELEMENT_LOOP(PCB->Data); + { + pcb_text_t *text; + text = &(element)->Name[PCB_ELEMNAME_IDX_VISIBLE()]; + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + continue; + texts_by_pos[nsel].text = text; + texts_by_pos[nsel].type = PCB_TYPE_ELEMENT_NAME; + texts_by_pos[nsel++].pos = coord(text, dir, point); + } + 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].type = PCB_TYPE_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; +} + + +/*! + * AlignText(X, [Lefts/Rights/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]])\n + * AlignText(Y, [Tops/Bottoms/Centers, [First/Last/pcb_crosshair/Average[, Gridless]]]) + * + * X or Y - Select which axis will move, other is untouched. \n + * Lefts, Rights, \n + * Tops, Bottoms, \n + * Centers - Pick alignment point within each element. \n + * NB: text objects have no Mark. \n + * First, Last, \n + * pcb_crosshair, \n + * Average - Alignment reference, First=Topmost/Leftmost, \n + * 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 + */ +static int aligntext(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int dir; + int point; + int reference; + int gridless; + pcb_coord_t q; + pcb_coord_t p, dp, dx, dy; + int changed = 0; + + if (argc < 1 || argc > 4) { + PCB_AFAIL(aligntext); + } + /* parse direction arg */ + switch ((dir = keyword(ARG(0)))) { + case K_X: + case K_Y: + break; + default: + PCB_AFAIL(aligntext); + } + /* parse point (within each element) which will be aligned */ + switch ((point = keyword(ARG(1)))) { + case K_Centers: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_AFAIL(aligntext); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_AFAIL(aligntext); + } + break; + case K_none: /* default value */ + if (dir == K_X) { + point = K_Lefts; + } + else { + point = K_Tops; + } + break; + default: + PCB_AFAIL(aligntext); + } + /* parse reference which will determine alignment coordinates */ + switch ((reference = keyword(ARG(2)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + reference = K_First; /* default value */ + break; + default: + PCB_AFAIL(aligntext); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(ARG(3))) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_AFAIL(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_ELEMENT_LOOP(PCB->Data); + { + pcb_text_t *text; + text = &(element)->Name[PCB_ELEMNAME_IDX_VISIBLE()]; + if (!PCB_FLAG_TEST(PCB_FLAG_SELECTED, 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_TYPE_ELEMENT_NAME, element, text, text, dx, dy); + changed = 1; + } + } + 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_TYPE_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(); + return 0; +} + +/*! + * DistributeText(X, [Lefts/Rights/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) \n + * DistributeText(Y, [Tops/Bottoms/Centers/Gaps, [First/Last/pcb_crosshair, First/Last/pcb_crosshair[, Gridless]]]) \n + * \n + * As with align, plus: \n + * \n + * Gaps - Make gaps even rather than spreading points evenly. \n + * First, Last, \n + * pcb_crosshair - Two arguments specifying both ends of the distribution, + * they can't both be the same. \n + * \n + * Defaults are Lefts/Tops, First, Last \n + * \n + * Distributed texts always retain the same relative order they had + * before they were distributed. \n + */ +static int distributetext(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int dir; + int point; + int refa, refb; + int gridless; + pcb_coord_t s, e, slack; + int divisor; + int changed = 0; + int i; + + if (argc < 1 || argc == 3 || argc > 4) { + PCB_AFAIL(distributetext); + } + /* parse direction arg */ + switch ((dir = keyword(ARG(0)))) { + case K_X: + case K_Y: + break; + default: + PCB_AFAIL(distributetext); + } + /* parse point (within each element) which will be distributed */ + switch ((point = keyword(ARG(1)))) { + case K_Centers: + case K_Gaps: + break; + case K_Lefts: + case K_Rights: + if (dir == K_Y) { + PCB_AFAIL(distributetext); + } + break; + case K_Tops: + case K_Bottoms: + if (dir == K_X) { + PCB_AFAIL(distributetext); + } + break; + case K_none: /* default value */ + if (dir == K_X) { + point = K_Lefts; + } + else { + point = K_Tops; + } + break; + default: + PCB_AFAIL(distributetext); + } + /* parse reference which will determine first distribution coordinate */ + switch ((refa = keyword(ARG(2)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refa = K_First; /* default value */ + break; + default: + PCB_AFAIL(distributetext); + } + /* parse reference which will determine final distribution coordinate */ + switch ((refb = keyword(ARG(3)))) { + case K_First: + case K_Last: + case K_Average: + case K_Crosshair: + break; + case K_none: + refb = K_Last; /* default value */ + break; + default: + PCB_AFAIL(distributetext); + } + if (refa == refb) { + PCB_AFAIL(distributetext); + } + /* optionally work off the grid (solar cells!) */ + switch (keyword(ARG(4))) { + case K_Gridless: + gridless = 1; + break; + case K_none: + gridless = 0; + break; + default: + PCB_AFAIL(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, x, y, dir, point, refa); + e = reference_coord(K_distributetext, x, 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; + int type = texts_by_pos[i].type; + 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; + /* need to know if the text is part of an element, + * all are PCB_TYPE_TEXT, but text associated with an + * element is also PCB_TYPE_ELEMENT_NAME. For undo, this is + * significant in search.c: SearchObjectByID. + * + * pcb_move_obj() is better as in aligntext(), but we + * didn't keep the element reference when sorting. + */ + pcb_text_move(text, dx, dy); + pcb_undo_add_obj_to_move(type, 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(); + return 0; +} + +static pcb_hid_action_t distaligntext_action_list[] = { + {"distributetext", NULL, distributetext, "Distribute Text Elements", distributetext_syntax}, + {"aligntext", NULL, aligntext, "Align Text Elements", aligntext_syntax} +}; + +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_hid_remove_actions_by_cookie(distaligntext_cookie); +} + +#include "dolists.h" +int pplg_init_distaligntext(void) +{ + PCB_REGISTER_ACTIONS(distaligntext_action_list, distaligntext_cookie); + return 0; +} Index: tags/1.2.7/src_plugins/distaligntext/distaligntext.pup =================================================================== --- tags/1.2.7/src_plugins/distaligntext/distaligntext.pup (nonexistent) +++ tags/1.2.7/src_plugins/distaligntext/distaligntext.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short distribute and align text +$long Same as distalign, operates on text objects. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/djopt/Makefile =================================================================== --- tags/1.2.7/src_plugins/djopt/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/djopt/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_djopt + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/djopt/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/djopt/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/djopt/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/djopt/djopt.c =================================================================== --- tags/1.2.7/src_plugins/djopt/djopt.c (nonexistent) +++ tags/1.2.7/src_plugins/djopt/djopt.c (revision 13657) @@ -0,0 +1,2654 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "hid_flags.h" +#include "hid_actions.h" +#include "djopt_conf.h" +#include "obj_line.h" +#include "obj_pinvia.h" +#include "event.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 (PCB->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_pin_t *via; + pcb_pad_t *pad; + pcb_pin_t *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_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (pin == c->pin) + return element->Name[1].TextString; + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + if (pad == c->pad) + return element->Name[1].TextString; + } + 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->Number, 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->Number, c->x, c->y, + c->pad->Point1.X, c->pad->Point1.Y, c->pad->Point2.X, c->pad->Point2.Y); + } + 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_TYPE_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_TYPE_LINE, NULL)); + 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) +{ + int diam = 0; + int i; + if (c->pin) + diam = djmax(c->pin->Thickness, diam); + if (c->via) + diam = djmax(c->via->Thickness, diam); + 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_TYPE_LINE, ls, l->line, 0, ld, 0); + l->layer = layer; +} + +static void remove_via_at(corner_s * c) +{ + pcb_remove_object(PCB_TYPE_VIA, 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_pin_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_TYPE_VIA, 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_TYPE_LINE_POINT, LAYER_PTR(c->lines[i]->layer), tl, &tl->Point1, x - (tl->Point1.X), y - (tl->Point1.Y)); + } + else { + pcb_move_obj(PCB_TYPE_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_gui->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_TYPE_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)) { + int th = c->pin ? c->pin->Thickness : c->via->Thickness; + 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_intersect_line_pin(c->pin ? c->pin : c->via, 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 + that aren't tented (assume they're test points). */ + if (!PCB_FLAG_THERM_TEST_ANY(c->via) + && c->via->Mask == 0) { + 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 = c->via->Thickness / 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_TYPE_LINE, NULL)); + /* 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_pin_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 = 0; + + dprintf("\ncorner %s\n", corner_name(c)); + if (c->pin || c->via) { + pin = c->pin ? c->pin : c->via; + close = pin->Thickness / 2; + left = c->x - close; + right = c->x + close; + bottom = c->y - close; + top = c->y + close; + } + else if (c->pad) { + close = c->pad->Thickness / 2 + 1; + left = djmin(c->pad->Point1.X, c->pad->Point2.X) - close; + right = djmax(c->pad->Point1.X, c->pad->Point2.X) + close; + bottom = djmin(c->pad->Point1.Y, c->pad->Point2.Y) - close; + top = djmax(c->pad->Point1.Y, c->pad->Point2.Y) + close; + if (c->pad->Point1.X == c->pad->Point2.X) { + int hy = (c->pad->Point1.Y + c->pad->Point2.Y) / 2; + dprintf("pad y %#mS %#mS hy %#mS c %#mS\n", c->pad->Point1.Y, c->pad->Point2.Y, hy, c->y); + if (c->y < hy) + top = hy; + else + bottom = hy + 1; + } + else { + int hx = (c->pad->Point1.X + c->pad->Point2.X) / 2; + dprintf("pad x %#mS %#mS hx %#mS c %#mS\n", c->pad->Point1.X, c->pad->Point2.X, hx, c->x); + if (c->x < hx) + right = hx; + else + left = hx + 1; + } + } + + 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; + + if (DELETED(c2)) + continue; + 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 > pin->Thickness / 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 pad_orient(pcb_pad_t * p) +{ + if (p->Point1.X == p->Point2.X) + return O_VERT; + if (p->Point1.Y == p->Point2.Y) + return O_HORIZ; + return DIAGONAL; +} + +static void padcleaner() +{ + line_s *l, *nextl; + int close; + 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_PAD_ALL_LOOP(PCB->Data); + { + int layerflag = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? LT_SOLDER : LT_COMPONENT; + + if (layer_type[l->layer] != layerflag) + continue; + + empty_rect(&r); + close = pad->Thickness / 2 + 1; + add_point_to_rect(&r, pad->Point1.X, pad->Point1.Y, close - SB / 2); + add_point_to_rect(&r, pad->Point2.X, pad->Point2.Y, close - SB / 2); + 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)) == pad_orient(pad)) { + dprintf + ("padcleaner %#mD-%#mD %#mS vs line %#mD-%#mD %#mS\n", + pad->Point1.X, pad->Point1.Y, pad->Point2.X, pad->Point2.Y, + pad->Thickness, l->s->x, l->s->y, l->e->x, l->e->y, l->line->Thickness); + remove_line(l); + goto next_line; + } + } + PCB_ENDALL_LOOP; + next_line:; + } +} + +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."; + +/* %start-doc actions djopt + +The different types of optimizations change your board in order to +reduce the total trace length and via count. + +@table @code + +@item debumpify +Looks for U-shaped traces that can be shortened or eliminated. + +@item unjaggy +Looks for corners which could be flipped to eliminate one or more +corners (i.e. jaggy lines become simpler). + +@item 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. + +@item 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). + +@item viatrim +Looks for traces that go from via to via, where moving that trace to a +different layer eliminates one or both vias. + +@item 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. + +@item splitlines +Looks for lines that pass through vias, pins, or pads, and splits them +into separate lines so they can be managed separately. + +@item auto +Performs the above options, repeating until no further optimizations +can be made. + +@item miter +Replaces 90 degree corners with a pair of 45 degree corners, to reduce +RF losses and trace length. + +@end table + +%end-doc */ + +static int pcb_act_DJopt(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *arg = argc > 0 ? argv[0] : NULL; + int layn, saved = 0; + corner_s *c; + +#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_ELEMENT_LOOP(PCB->Data); + PCB_PIN_LOOP(element); + { + c = find_corner(pin->X, pin->Y, -1); + c->pin = pin; + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + int layern = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? solder_layer : component_layer; + line_s *ls = (line_s *) malloc(sizeof(line_s)); + ls->next = lines; + lines = ls; + ls->is_pad = 1; + ls->s = find_corner(pad->Point1.X, pad->Point1.Y, layern); + ls->s->pad = pad; + ls->e = find_corner(pad->Point2.X, pad->Point2.Y, layern); + ls->e->pad = pad; + ls->layer = layern; + ls->line = (pcb_line_t *) pad; + add_line_to_corner(ls, ls->s); + add_line_to_corner(ls, ls->e); + + } + PCB_END_LOOP; + PCB_END_LOOP; + PCB_VIA_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(via->X, via->Y, -1); + c->via = via; + } + 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; + + /* don't mess with thermals */ + if (PCB_FLAG_TEST(PCB_FLAG_USETHERMAL, 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(); + return 0; +} + +pcb_hid_action_t djopt_action_list[] = { + {"djopt", 0, 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_hid_remove_actions_by_cookie(djopt_cookie); + conf_unreg_fields("plugins/djopt/"); +} + +#include "dolists.h" +int pplg_init_djopt(void) +{ +#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/1.2.7/src_plugins/djopt/djopt.h =================================================================== --- tags/1.2.7/src_plugins/djopt/djopt.h (nonexistent) +++ tags/1.2.7/src_plugins/djopt/djopt.h (revision 13657) @@ -0,0 +1,34 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * DJ Delorie, 334 North Road, Deerfield NH 03037-1110, USA + * dj@delorie.com + * + */ + +#ifndef PCB_DJOPT_H +#define PCB_DJOPT_H + +#include "config.h" + +int 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/1.2.7/src_plugins/djopt/djopt.pup =================================================================== --- tags/1.2.7/src_plugins/djopt/djopt.pup (nonexistent) +++ tags/1.2.7/src_plugins/djopt/djopt.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short djopt board optimization +$long Various board optimization algorithms. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/djopt/djopt_conf.h =================================================================== --- tags/1.2.7/src_plugins/djopt/djopt_conf.h (nonexistent) +++ tags/1.2.7/src_plugins/djopt/djopt_conf.h (revision 13657) @@ -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/1.2.7/src_plugins/draw_csect/Makefile =================================================================== --- tags/1.2.7/src_plugins/draw_csect/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/draw_csect/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_csect + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/draw_csect/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/draw_csect/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/draw_csect/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/draw_csect/draw_csect.c =================================================================== --- tags/1.2.7/src_plugins/draw_csect/draw_csect.c (nonexistent) +++ tags/1.2.7/src_plugins/draw_csect/draw_csect.c (revision 13657) @@ -0,0 +1,899 @@ +/* + * 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. + * + */ + +/* 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 "hid_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_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; + + t.X = PCB_MM_TO_COORD(x); + t.Y = PCB_MM_TO_COORD(y); + t.TextString = (char *)txt; + t.Direction = dir; + t.Scale = scale; + t.fid = 0; /* use the default font */ + t.Flags = pcb_no_flags(); + pcb_text_draw_(&t, 0, 0); + 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; + + t.X = x; + t.Y = y; + t.TextString = (char *)txt; + t.Direction = dir; + t.Scale = scale; + t.fid = 0; /* use the default font */ + t.Flags = pcb_no_flags(); + pcb_text_draw_(&t, th, 0); + 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 char *bgcolor, const char *fgcolor) +{ + static pcb_text_t t; + + t.X = PCB_MM_TO_COORD(x); + t.Y = PCB_MM_TO_COORD(y); + t.TextString = (char *)txt; + t.Direction = 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_(&t, 1000000, 0); + } + + pcb_gui->set_color(gc, fgcolor); + pcb_text_draw_(&t, 0, 0); + + 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_(&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_(&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; +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; +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; + +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 char *color = "#ff0000"; + + if ((!g->valid) || (gid == drag_gid) || (gid == drag_gid_subst)) + continue; + else if (g->type & 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->type & PCB_LYT_SUBSTRATE) { + stepf = stepb = 7; + th = 10; + color = COLOR_SUBSTRATE; + } + else if (g->type & PCB_LYT_SILK) { + th = 5; + color = COLOR_SILK; + stepb = 3; + } + else if (g->type & PCB_LYT_MASK) { + th = 5; + color = COLOR_MASK; + stepb = 9; + } + else if (g->type & PCB_LYT_PASTE) { + th = 5; + color = COLOR_PASTE; + stepf = 9; + } + else if (g->type & PCB_LYT_MISC) { + th = 5; + color = COLOR_MISC; + stepf = 3; + } + else if (g->type & PCB_LYT_OUTLINE) { + 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)); + } + + x=20; + 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 ((drag_lid >= 0) || (drag_addgrp | drag_delgrp | drag_addlayer | drag_dellayer) || (drag_gid >= 0)) { + pcb_gui->set_color(gc, "#000000"); + + /* 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(void *widget, 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_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_OUTLINE) && (pcb_layergrp_flags(PCB, gid - 2) & PCB_LYT_SUBSTRATE)) + drag_gid_subst = gid - 2; + res = 1; + } + } + break; + case PCB_HID_MOUSE_RELEASE: + if (drag_addgrp) { + if (gactive >= 0) { + pcb_layergrp_t *g; + g = pcb_layergrp_insert_after(PCB, gactive); + g->name = NULL; + g->type = PCB_LYT_INTERN | PCB_LYT_SUBSTRATE; + g->valid = 1; + g = pcb_layergrp_insert_after(PCB, gactive); + g->name = pcb_strdup("Intern"); + g->type = 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_hid_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; + break; + case PCB_HID_MOUSE_POPUP: + lid = get_layer_coords(x, y); + if (lid >= 0) { + pcb_layervis_change_group_vis(lid, 1, 1); + pcb_hid_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_hid_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 int pcb_act_dump_csect(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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->type & PCB_LYT_VIRTUAL) continue; + else if (g->type & PCB_LYT_COPPER) type_gfx = "===="; + else if (g->type & PCB_LYT_SUBSTRATE) type_gfx = "xxxx"; + else if (g->type & PCB_LYT_SILK) type_gfx = "silk"; + else if (g->type & PCB_LYT_MASK) type_gfx = "mask"; + else if (g->type & PCB_LYT_PASTE) type_gfx = "pst."; + else if (g->type & PCB_LYT_MISC) type_gfx = "misc"; + else if (g->type & PCB_LYT_OUTLINE) 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); + } + } + return 0; +} + +static const char *draw_csect_cookie = "draw_csect"; + +pcb_hid_action_t draw_csect_action_list[] = { + {"DumpCsect", 0, 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_hid_remove_actions_by_cookie(draw_csect_cookie); +} + +#include "dolists.h" + +int pplg_init_draw_csect(void) +{ + PCB_REGISTER_ACTIONS(draw_csect_action_list, draw_csect_cookie) + + pcb_stub_draw_csect = draw_csect; + pcb_stub_draw_csect_mouse_ev = mouse_csect; + + return 0; +} Index: tags/1.2.7/src_plugins/draw_csect/draw_csect.pup =================================================================== --- tags/1.2.7/src_plugins/draw_csect/draw_csect.pup (nonexistent) +++ tags/1.2.7/src_plugins/draw_csect/draw_csect.pup (revision 13657) @@ -0,0 +1,5 @@ +$class feature +$short draw cross-section (layers) +$long Draw cross section and layer map. +$state WIP +default disable Index: tags/1.2.7/src_plugins/draw_fab/Makefile =================================================================== --- tags/1.2.7/src_plugins/draw_fab/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/draw_fab/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fab + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/draw_fab/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/draw_fab/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/draw_fab/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/draw_fab/draw_fab.c =================================================================== --- tags/1.2.7/src_plugins/draw_fab/draw_fab.c (nonexistent) +++ tags/1.2.7/src_plugins/draw_fab/draw_fab.c (revision 13657) @@ -0,0 +1,345 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* 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 "obj_all.h" +#include "plugins.h" +#include "stub_draw.h" +#include "draw_fab_conf.h" +#include "conf_core.h" +#include "obj_pstk_inlines.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_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); + t.Direction = 0; + 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_(&t, 0,0); + 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(DrillInfoTypePtr AllDrills) +{ + int n, ds = 0; + for (n = AllDrills->DrillN - 1; n >= 0; n--) { + DrillTypePtr drill = &(AllDrills->Drill[n]); + if (drill->PinCount + drill->ViaCount > drill->UnplatedCount) + ds++; + if (drill->UnplatedCount) + ds++; + } + return ds; +} + + +static int DrawFab_overhang(void) +{ + DrillInfoTypePtr AllDrills = GetDrillInfo(PCB->Data); + int ds = count_drill_lines(AllDrills); + if (ds < 4) + ds = 4; + return (ds + 2) * TEXT_LINE; +} + +static void DrawFab(pcb_hid_gc_t gc, const pcb_hid_expose_ctx_t *e) +{ + DrillInfoTypePtr AllDrills; + int i, n, yoff, total_drills = 0, ds = 0, found; + char utcTime[64]; + AllDrills = GetDrillInfo(PCB->Data); + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + RoundDrillInfo(AllDrills, PCB_MIL_TO_COORD(1)); + else + RoundDrillInfo(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_gui->set_line_width(gc, FAB_LINE_W); + + for (n = AllDrills->DrillN - 1; n >= 0; n--) { + int plated_sym = -1, unplated_sym = -1; + DrillTypePtr 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; + if ((drill->hole[i]->type == PCB_OBJ_PIN) || (drill->hole[i]->type == PCB_OBJ_VIA)) { + pcb_pin_t *pin = (pcb_pin_t *)drill->hole[i]; + unplated = PCB_FLAG_TEST(PCB_FLAG_HOLE, pin); + x = pin->X; + y = pin->Y; + } + else if (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(gc, PCB_MIL_TO_COORD(1350), yoff, PCB_MIL_TO_COORD(2), "YES"); + text_at(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(gc, PCB_MIL_TO_COORD(1400), yoff, PCB_MIL_TO_COORD(2), "NO"); + text_at(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(gc, PCB_MIL_TO_COORD(450), yoff, PCB_MIL_TO_COORD(2), "%0.3f", PCB_COORD_TO_INCH(drill->DrillSize)); + else + text_at(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(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(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(gc, 0, yoff, PCB_MIL_TO_COORD(9), "Symbol"); + if (conf_core.editor.grid_unit->family == PCB_UNIT_IMPERIAL) + text_at(gc, PCB_MIL_TO_COORD(410), yoff, PCB_MIL_TO_COORD(9), "Diam. (Inch)"); + else + text_at(gc, PCB_MIL_TO_COORD(410), yoff, PCB_MIL_TO_COORD(9), "Diam. (mm)"); + text_at(gc, PCB_MIL_TO_COORD(950), yoff, PCB_MIL_TO_COORD(9), "Count"); + text_at(gc, PCB_MIL_TO_COORD(1300), yoff, PCB_MIL_TO_COORD(9), "Plated?"); + yoff -= TEXT_LINE; + text_at(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); + if ((pcb_layer_flags(PCB, i) & PCB_LYT_OUTLINE) && (!PCB_RTREE_EMPTY(l->line_tree) || !PCB_RTREE_EMPTY(l->arc_tree))) { + found = 1; + break; + } + } + if (!found) { + pcb_gui->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_gui->set_line_width(gc, FAB_LINE_W); + text_at(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(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)); + } + else { + pcb_layer_t *layer = LAYER_PTR(i); + pcb_gui->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_(text, 0, 0); + } + PCB_END_LOOP; + pcb_gui->set_line_width(gc, FAB_LINE_W); + text_at(gc, PCB->MaxWidth / 2, PCB->MaxHeight + PCB_MIL_TO_COORD(20), 1, "Board outline is the centerline of this path"); + } + yoff -= TEXT_LINE; + + text_at(gc, PCB_MIL_TO_COORD(2000), yoff, 0, "Date: %s", utcTime); + yoff -= TEXT_LINE; + text_at(gc, PCB_MIL_TO_COORD(2000), yoff, 0, "Author: %s", pcb_author()); + yoff -= TEXT_LINE; + text_at(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_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/1.2.7/src_plugins/draw_fab/draw_fab.pup =================================================================== --- tags/1.2.7/src_plugins/draw_fab/draw_fab.pup (nonexistent) +++ tags/1.2.7/src_plugins/draw_fab/draw_fab.pup (revision 13657) @@ -0,0 +1,9 @@ +$class feature +$short fab layer in some exports +$long Draw the fab layer (for various exporters). +$state works +default buildin + +# for drill.[ch] +dep report +autoload 1 Index: tags/1.2.7/src_plugins/draw_fab/draw_fab_conf.h =================================================================== --- tags/1.2.7/src_plugins/draw_fab/draw_fab_conf.h (nonexistent) +++ tags/1.2.7/src_plugins/draw_fab/draw_fab_conf.h (revision 13657) @@ -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/1.2.7/src_plugins/draw_fontsel/Makefile =================================================================== --- tags/1.2.7/src_plugins/draw_fontsel/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/draw_fontsel/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fontsel + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/draw_fontsel/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/draw_fontsel/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/draw_fontsel/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/draw_fontsel/draw_fontsel.c =================================================================== --- tags/1.2.7/src_plugins/draw_fontsel/draw_fontsel.c (nonexistent) +++ tags/1.2.7/src_plugins/draw_fontsel/draw_fontsel.c (revision 13657) @@ -0,0 +1,266 @@ +/* + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +/* printing routines */ +#include "config.h" + +#include + +#include "board.h" +#include "build_run.h" +#include "data.h" +#include "draw.h" +#include "font.h" +#include "const.h" +#include "hid_actions.h" +#include "obj_all.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.Direction = 0; + t.Scale = scale; + t.fid = fid; + t.Flags = pcb_no_flags(); + pcb_text_draw_(&t, 0, 0); + 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_(&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, "#000000"); + 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, "#AA0033"); + 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; +int font_new_y1, font_new_y2; +int font_replace_y1, font_replace_y2; +int font_del_y1, font_del_y2; + +pcb_text_t *fontsel_txt = NULL; +pcb_layer_t *fontsel_layer = NULL; +int fontsel_txt_type = 0; + +static void pcb_draw_font(pcb_hid_gc_t gc, pcb_font_t *f, int x, int *y) +{ + char txt[256]; + pcb_text_t *t; + const char *nm; + int y_old = *y; + pcb_font_id_t target_fid = (fontsel_txt == NULL) ? conf_core.design.text_font_id : fontsel_txt->fid; + + nm = (f->name == NULL) ? "" : f->name; + pcb_snprintf(txt, sizeof(txt), "#%d [abc ABC 123] %s", f->id, nm); + + dchkbox(gc, x-4, *y, (f->id == target_fid)); + + pcb_gui->set_color(gc, "#000000"); + t = dtext(x, *y, 200, f->id, txt); + 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) +{ + int y = 10; + pcb_text_t *t; + + pcb_gui->set_color(gc, "#FF0000"); + dtext(0, 0, 300, 0, "Select font"); + + font_coords = 0; + pcb_draw_font(gc, &PCB->fontkit.dflt, 10, &y); + + 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, 10, &y); + } + + /* New font */ + pcb_gui->set_color(gc, "#000000"); + t = dtext(5, y, 250, 0, "[Load font from file]"); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + font_new_y1 = y; + y += pcb_round(PCB_COORD_TO_MM(t->BoundingBox.Y2 - t->BoundingBox.Y1) + 0.5); + font_new_y2 = y; + + /* Replace font */ + pcb_gui->set_color(gc, "#000000"); + t = dtext(5, y, 250, 0, "[Replace font]"); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + font_replace_y1 = y; + y += pcb_round(PCB_COORD_TO_MM(t->BoundingBox.Y2 - t->BoundingBox.Y1) + 0.5); + font_replace_y2 = y; + + /* Del font */ + pcb_gui->set_color(gc, "#550000"); + t = dtext(5, y, 250, 0, "[Remove current font]"); + pcb_text_bbox(pcb_font(PCB, 0, 1), t); + font_del_y1 = y; + y += pcb_round(PCB_COORD_TO_MM(t->BoundingBox.Y2 - t->BoundingBox.Y1) + 0.5); + font_del_y2 = y; + +} + +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(void *widget, pcb_hid_mouse_ev_t kind, pcb_coord_t x, pcb_coord_t y) +{ + 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 (fontsel_txt == NULL) { + char sval[128]; + sprintf(sval, "%ld", fid); + conf_set(CFR_DESIGN, "design/text_font_id", 0, sval, POL_OVERWRITE); + } + else { + switch(fontsel_txt_type) { + case PCB_TYPE_TEXT: + pcb_text_set_font(fontsel_layer, fontsel_txt, fid); + break; + case PCB_TYPE_ELEMENT_NAME: + { + int which; + pcb_element_t *e = (pcb_element_t *)fontsel_layer; + for(which = 0; which <= PCB_ELEMNAME_IDX_VALUE; which++) { + if (&e->Name[which] == fontsel_txt) { + pcb_element_text_set_font(PCB, PCB->Data, e, which, fid); + break; + } + } + } + break; + } + pcb_gui->invalidate_all(); + } + return 1; + } + else if ((ymm >= font_new_y1) && (ymm <= font_new_y2)) { + pcb_hid_actionl("LoadFontFrom", NULL); /* modal, blocking */ + return 1; + } + else if ((ymm >= font_replace_y1) && (ymm <= font_replace_y2)) { + char file[1] = "", id[5]; + pcb_snprintf(id, sizeof(id), "%ld", conf_core.design.text_font_id); + pcb_hid_actionl("LoadFontFrom", file, id, NULL); /* modal, blocking */ + return 1; + } + else if ((ymm >= font_del_y1) && (ymm <= font_del_y2)) { + if (conf_core.design.text_font_id == 0) { + pcb_message(PCB_MSG_ERROR, "Can not remove the default font.\n"); + return 0; + } + pcb_del_font(&PCB->fontkit, conf_core.design.text_font_id); + conf_set(CFR_DESIGN, "design/text_font_id", 0, "0", POL_OVERWRITE); + return 1; + } + } + 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_stub_draw_fontsel = pcb_draw_fontsel; + pcb_stub_draw_fontsel_mouse_ev = pcb_mouse_fontsel; + pcb_stub_draw_fontsel_text_obj = &fontsel_txt; + pcb_stub_draw_fontsel_layer_obj = &fontsel_layer; + pcb_stub_draw_fontsel_text_type = &fontsel_txt_type; + + return 0; +} Index: tags/1.2.7/src_plugins/draw_fontsel/draw_fontsel.pup =================================================================== --- tags/1.2.7/src_plugins/draw_fontsel/draw_fontsel.pup (nonexistent) +++ tags/1.2.7/src_plugins/draw_fontsel/draw_fontsel.pup (revision 13657) @@ -0,0 +1,5 @@ +$class feature +$short font selection GUI +$long Draw the font selector GUI +$state WIP +default disable Index: tags/1.2.7/src_plugins/export_bboard/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_bboard/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_bboard/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bboard + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_bboard/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_bboard/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_bboard/Plug.tmpasm (revision 13657) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_bboard} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_bboard/bboard.o @] + +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/1.2.7/src_plugins/export_bboard/bboard.c =================================================================== --- tags/1.2.7/src_plugins/export_bboard/bboard.c (nonexistent) +++ tags/1.2.7/src_plugins/export_bboard/bboard.c (revision 13657) @@ -0,0 +1,606 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +#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 "plugins.h" +#include "compat_misc.h" +#include "compat_fs.h" +#include "misc_util.h" +#include "obj_all.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_helper.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) +{ + static char *last_made_filename = 0; + if (PCB) + pcb_derive_default_filename(PCB->Filename, &bboard_options[HA_bboardfile], ".png", &last_made_filename); + + 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 group, int skipsolder) +{ + if ((flags & PCB_LYT_INVIS) || (flags & PCB_LYT_ASSY) || (flags & PCB_LYT_OUTLINE)) + 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->meta.real.Attributes), "BBoard::LayerColor")) != NULL) { + if (clr[0] == '#') { + if (sscanf(&(clr[1]), "%02x%02x%02x", &r, &g, &b) == 3) + goto ok; + } + } + + if (layer->meta.real.color && (layer->meta.real.color[0] == '#')) { + if (sscanf(&(layer->meta.real.color[1]), "%02x%02x%02x", &r, &g, &b) == 3) + goto ok; + } + + /* 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_element_t * element, 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(&(element->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); + } + 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); + } + 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(&(element->Attributes), "Footprint::File"); + if (s) { + 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); + } + if (!fname) + fname = bboard_get_model_filename(s, NULL, pcb_false); + } + } + if (!fname) { + 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); + } + } + + 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(&(element->Attributes), "BBoard::Offset"); + + /* Parse values with units... */ + if (s) { + bboard_parse_offset(s, &ox, &oy); + } + } + ex = bboard_scale_coord(element->MarkX); + ey = bboard_scale_coord(element->MarkY); + + cairo_save(bboard_cairo_ctx); + + if ((model_angle = pcb_attribute_get(&(element->Attributes), "Footprint::RotationTracking")) != NULL) { + sscanf(model_angle, "%lf", &tmp_angle); + } + + + cairo_translate(bboard_cairo_ctx, ex, ey); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) { + 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); + + /* 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; + + /* draw all wires from all valid layers */ + for (i = pcb_max_layer; i >= 0; i--) { + unsigned int flg = pcb_layer_flags(PCB, i); + if (flg & PCB_LYT_SILK) + continue; + if (bboard_validate_layer(flg, pcb_layer_get_group(PCB, i), 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])); + { +#warning 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 void bboard_parse_arguments(int *argc, char ***argv) +{ + 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(int x, int 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) +{ + 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/1.2.7/src_plugins/export_bboard/export_bboard.pup =================================================================== --- tags/1.2.7/src_plugins/export_bboard/export_bboard.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_bboard/export_bboard.pup (revision 13657) @@ -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/1.2.7/src_plugins/export_bom/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_bom/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_bom/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bom + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_bom/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_bom/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_bom/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_bom/bom.c =================================================================== --- tags/1.2.7/src_plugins/export_bom/bom.c (nonexistent) +++ tags/1.2.7/src_plugins/export_bom/bom.c (revision 13657) @@ -0,0 +1,325 @@ +#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_helper.h" +#include "hid_init.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) +{ + static char *last_bom_filename = NULL; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &bom_options[HA_bomfile], ".bom", &last_bom_filename); + + 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 element 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_ELEMENT_LOOP(PCB->Data); + { + /* insert this component into the bill of materials list */ + bom = bom_insert((char *) PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), + (char *) PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element)), (char *) PCB_UNKNOWN(PCB_ELEM_NAME_VALUE(element)), bom); + } + PCB_END_LOOP; + + fp = pcb_fopen(bom_filename, "w"); + if (!fp) { + pcb_gui->log("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 void bom_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(bom_options, sizeof(bom_options) / sizeof(bom_options[0]), bom_cookie, 0); + 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) +{ + 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/1.2.7/src_plugins/export_bom/export_bom.pup =================================================================== --- tags/1.2.7/src_plugins/export_bom/export_bom.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_bom/export_bom.pup (revision 13657) @@ -0,0 +1,8 @@ +$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 +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_dsn/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_dsn/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_dsn/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dsn + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_dsn/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_dsn/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_dsn/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_dsn/dsn.c =================================================================== --- tags/1.2.7/src_plugins/export_dsn/dsn.c (nonexistent) +++ tags/1.2.7/src_plugins/export_dsn/dsn.c (revision 13657) @@ -0,0 +1,731 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * Specctra .dsn export HID + * Copyright (C) 2008, 2011 Josh Jordan, Dan McMahill, and Jared Casper + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* +This program exports specctra .dsn files from geda .pcb 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 + +#include "board.h" +#include "data.h" +#include "error.h" +#include "rats.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 "hid.h" +#include "hid_draw_helpers.h" +#include "hid_nogui.h" +#include "hid_actions.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "plugins.h" +#include "obj_line.h" +#include "obj_pinvia.h" + +static const char *dsn_cookie = "dsn exporter"; + +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) +{ + static char *last_dsn_filename = 0; + if (PCB) { + pcb_derive_default_filename(PCB->Filename, &dsn_options[HA_dsnfile], ".dsn", &last_dsn_filename); + } + if (n) + *n = NUM_OPTIONS; + return dsn_options; +} + + +/* this function is mostly ripped from bom.c */ +static pcb_point_t get_centroid(pcb_element_t * element) +{ + pcb_point_t centroid; + double sumx = 0.0, sumy = 0.0; + int pin_cnt = 0; + + PCB_PIN_LOOP(element); + { + sumx += (double) pin->X; + sumy += (double) pin->Y; + pin_cnt++; + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + sumx += (pad->Point1.X + pad->Point2.X) / 2.0; + sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; + pin_cnt++; + } + PCB_END_LOOP; + + if (pin_cnt > 0) { + centroid.X = sumx / (double) pin_cnt; + centroid.Y = PCB->MaxHeight - (sumy / (double) pin_cnt); + } + else { + centroid.X = 0; + centroid.Y = 0; + } + return centroid; +} + +static GList *layerlist = NULL; /* contain routing layers */ + +static void print_structure(FILE * fp) +{ + pcb_layergrp_id_t group, top_group, bot_group; + pcb_layer_id_t top_layer, bot_layer; + + 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); + + top_layer = PCB->LayerGroups.grp[top_group].lid[0]; + bot_layer = PCB->LayerGroups.grp[bot_group].lid[0]; + + + g_list_free(layerlist); /* might be around from the last export */ + + if (PCB->Data->Layer[top_layer].meta.real.vis) { + layerlist = g_list_append(layerlist, &PCB->Data->Layer[top_layer]); + } + else { + pcb_message(PCB_MSG_WARNING, "WARNING! DSN export does not include the top layer. " + "Router will consider an inner layer to be the \"top\" layer.\n"); + } + + for (group = 0; group < pcb_max_group(PCB); group++) { + pcb_layer_t *first_layer; + unsigned int gflg = pcb_layergrp_flags(PCB, group); + + if (gflg & PCB_LYT_SILK) + continue; + + if (group == top_group || group == bot_group) + continue; + + if (PCB->LayerGroups.grp[group].len < 1) + continue; + + first_layer = &PCB->Data->Layer[PCB->LayerGroups.grp[group].lid[0]]; + if (!first_layer->meta.real.vis) + continue; + + layerlist = g_list_append(layerlist, first_layer); + + if (group < top_group) { + pcb_message(PCB_MSG_WARNING, "WARNING! DSN export moved layer group with the \"%s\" layer " + "after the top layer group. DSN files must have the top " "layer first.\n", first_layer->name); + } + + if (group > bot_group) { + pcb_message(PCB_MSG_WARNING, "WARNING! DSN export moved layer group with the \"%s\" layer " + "before the bottom layer group. DSN files must have the " "bottom layer last.\n", first_layer->name); + } + + PCB_COPPER_GROUP_LOOP(PCB->Data, group); + { + if (entry > 0) { + pcb_message(PCB_MSG_WARNING, "WARNING! DSN export squashed layer \"%s\" into layer " + "\"%s\", DSN files do not have layer groups.", layer->name, first_layer->name); + } + } + PCB_END_LOOP; + } + + if (PCB->Data->Layer[bot_layer].meta.real.vis) { + layerlist = g_list_append(layerlist, &PCB->Data->Layer[bot_layer]); + } + else { + pcb_message(PCB_MSG_WARNING, "WARNING! DSN export does not include the bottom layer. " + "Router will consider an inner layer to be the \"bottom\" layer.\n"); + } + + fprintf(fp, " (structure\n"); + + for (GList * iter = layerlist; iter; iter = g_list_next(iter)) { + pcb_layer_t *layer = iter->data; + char *layeropts = pcb_strdup("(type signal)"); + + if (!(pcb_layer_flags_(layer) & PCB_LYT_COPPER)) + continue; + + /* see if layer has same name as a net and make it a power layer */ + /* loop thru all nets */ + for (int ni = 0; ni < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; ni++) { + char *nname; + nname = PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[ni].Name + 2; + if (!strcmp(layer->name, nname)) { + g_free(layeropts); + layeropts = pcb_strdup_printf("(type power) (use_net \"%s\")", layer->name); + } + } + fprintf(fp, " (layer \"%s\"\n", layer->name); + fprintf(fp, " %s\n", layeropts); + fprintf(fp, " )\n"); + g_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_ELEMENT_LOOP(PCB->Data); + { + char *ename; + pcb_point_t ecentroid = get_centroid(element); + char *side = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? "back" : "front"; + ename = PCB_ELEM_NAME_REFDES(element); + if (ename != NULL) + ename = pcb_strdup(ename); + else + ename = pcb_strdup("null"); + pcb_fprintf(fp, " (component %d\n", element->ID); + pcb_fprintf(fp, " (place \"%s\" %.6mm %.6mm %s 0 (PN 0))\n", ename, ecentroid.X, ecentroid.Y, side); + pcb_fprintf(fp, " )\n"); + g_free(ename); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(PCB->Data); + { + char *ename; + pcb_coord_t ox, oy; + char *side; + pcb_layer_type_t lyt = PCB_LYT_TOP; + + if (subc->aux_layer != NULL) + lyt = pcb_layer_flags_(subc->aux_layer); + side = (lyt & PCB_LYT_BOTTOM) ? "back" : "front"; + + assert(pcb_subc_get_origin(subc, &ox, &oy) == 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, oy, side); + pcb_fprintf(fp, " )\n"); + g_free(ename); + } + PCB_END_LOOP; + + PCB_VIA_LOOP(PCB->Data); + { /* add mounting holes */ + pcb_fprintf(fp, " (component %d\n", via->ID); + pcb_fprintf(fp, " (place %d %.6mm %.6mm %s 0 (PN 0))\n", via->ID, via->X, (PCB->MaxHeight - via->Y), "front"); + pcb_fprintf(fp, " )\n"); + } + PCB_END_LOOP; + fprintf(fp, " )\n"); +} + +static void add_padstack(GList **pads, char *padstack) +{ + if (!g_list_find_custom(*pads, padstack, (GCompareFunc) strcmp)) + *pads = g_list_append(*pads, padstack); + else + free(padstack); +} + +static void print_pin(FILE *fp, GList **pads, pcb_pin_t *pin, pcb_point_t centroid, int partsidesign, int partside) +{ + char *padstack; + pcb_coord_t ty; + pcb_coord_t pinthickness; + pcb_coord_t lx, ly; /* hold local pin coordinates */ + ty = PCB->MaxHeight - pin->Y; + pinthickness = pin->Thickness; + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) + padstack = pcb_strdup_printf("Th_square_%mI", pinthickness); + else + padstack = pcb_strdup_printf("Th_round_%mI", pinthickness); + lx = (pin->X - centroid.X) * partsidesign; + ly = (centroid.Y - ty) * -1; + + if (!pin->Number) { /* if pin is null just make it a keepout */ + for (GList * iter = layerlist; iter; iter = g_list_next(iter)) { + pcb_layer_t *lay = iter->data; + pcb_fprintf(fp, " (keepout \"\" (circle \"%s\" %.6mm %.6mm %.6mm))\n", lay->name, pinthickness, lx, ly); + } + } + else { + pcb_fprintf(fp, " (pin %s \"%s\" %.6mm %.6mm)\n", padstack, pin->Number, lx, ly); + } + + add_padstack(pads, padstack); +} + +static void print_pad(FILE *fp, GList **pads, pcb_pad_t *pad, pcb_point_t centroid, int partsidesign, int partside) +{ + gchar *padstack; + pcb_coord_t xlen, ylen, xc, yc, p1y, p2y; + pcb_coord_t lx, ly; /* store local coordinates for pins */ + p1y = PCB->MaxHeight - pad->Point1.Y; + p2y = PCB->MaxHeight - pad->Point2.Y; + /* pad dimensions are unusual- + the width is thickness and length is point difference plus thickness */ + xlen = ABS(pad->Point1.X - pad->Point2.X); + if (xlen == 0) { + xlen = pad->Thickness; + ylen = ABS(p1y - p2y) + pad->Thickness; + } + else { + ylen = pad->Thickness; + xlen += pad->Thickness; + } + xc = (pad->Point1.X + pad->Point2.X) / 2; + yc = (p1y + p2y) / 2; + lx = (xc - centroid.X) * partsidesign; + ly = (centroid.Y - yc) * -1; + padstack = pcb_strdup_printf("Smd_rect_%mIx%mI", xlen, ylen); + + if (!pad->Number) { /* if pad is null just make it a keepout */ + pcb_layer_t *lay; + lay = g_list_nth_data(layerlist, partside); + pcb_fprintf(fp, " (keepout \"\" (rect \"%s\" %.6mm %.6mm %.6mm %.6mm))\n", + lay->name, lx - xlen / 2, ly - ylen / 2, lx + xlen / 2, ly + ylen / 2); + } + else { + pcb_fprintf(fp, " (pin %s \"%s\" %.6mm %.6mm)\n", padstack, pad->Number, lx, ly); + } + + add_padstack(pads, padstack); +} + +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_side) +{ + if (poly->term != NULL) { + pcb_layer_t *lay = g_list_nth_data(layerlist, term_side); + char *padstack = pcb_strdup_printf("Term_poly_%ld", poly->ID); + char tmp[512]; + pcb_poly_it_t it; + pcb_polyarea_t *pa; + int fld; + + pcb_fprintf(fp, " (pin %s \"%s\" %.6mm %.6mm)\n", padstack, poly->term, ox, oy); + + gds_append_str(term_shapes, " (padstack "); + gds_append_str(term_shapes, padstack); + gds_append_str(term_shapes, "\n"); + + 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_snprintf(tmp, sizeof(tmp), " (shape (polygon \"%s\" 0", lay->name); + 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, y - oy); + gds_append_str(term_shapes, tmp); + fld++; + } + + gds_append_str(term_shapes, "\n ))\n"); + gds_append_str(term_shapes, " (attach off)\n"); + } + } + gds_append_str(term_shapes, " )\n"); + } +} + + +static void print_library(FILE * fp) +{ + GList *pads = NULL, *iter; /* contain unique pad names */ + gchar *padstack; + gds_t term_shapes; + + gds_init(&term_shapes); + + fprintf(fp, " (library\n"); + PCB_ELEMENT_LOOP(PCB->Data); + { + int partside = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? g_list_length(layerlist) - 1 : 0; + int partsidesign = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element) ? -1 : 1; + pcb_point_t centroid = get_centroid(element); + fprintf(fp, " (image %ld\n", element->ID); /* map every element by ID */ + /* loop thru pins and pads to add to image */ + PCB_PIN_LOOP(element); + { + print_pin(fp, &pads, pin, centroid, partsidesign, partside); + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + print_pad(fp, &pads, pad, centroid, partsidesign, partside); + } + PCB_END_LOOP; + fprintf(fp, " )\n"); + } + PCB_END_LOOP; + + PCB_SUBC_LOOP(PCB->Data); + { + pcb_coord_t ox, oy; + pcb_point_t centroid; + int partside, partsidesign, subc_on_solder = 0; + + pcb_subc_get_side(subc, &subc_on_solder); + partside = subc_on_solder ? g_list_length(layerlist) - 1 : 0; + partsidesign = subc_on_solder ? -1 : 1; + + pcb_subc_get_origin(subc, &ox, &oy); + centroid.X = ox; + centroid.Y = 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))) { + int termside = (lyt & PCB_LYT_BOTTOM) ? g_list_length(layerlist) - 1 : 0; + print_term_poly(fp, &term_shapes, polygon, ox, oy, termside); + } + } + PCB_ENDALL_LOOP; + + PCB_VIA_LOOP(subc->data); + { + print_pin(fp, &pads, via, centroid, partsidesign, partside); + } + PCB_END_LOOP; + + fprintf(fp, " )\n"); + } + PCB_END_LOOP; + + PCB_VIA_LOOP(PCB->Data); + { /* add mounting holes and vias */ + fprintf(fp, " (image %ld\n", via->ID); /* map every via by ID */ + /* for mounting holes, clearance is added to thickness for higher total clearance */ + padstack = pcb_strdup_printf("Th_round_%mI", via->Thickness + via->Clearance); + fprintf(fp, " (pin %s 1 0 0)\n", padstack); /* only 1 pin, 0,0 puts it right on component placement spot */ + fprintf(fp, " )\n"); + + add_padstack(&pads, padstack); + } + PCB_END_LOOP; + + /* loop thru padstacks and define them all */ + for (iter = pads; iter; iter = g_list_next(iter)) { + pcb_coord_t dim1, dim2; + long int dim1l, dim2l; + padstack = iter->data; + fprintf(fp, " (padstack %s\n", padstack); + + /* print info about pad here */ + if (sscanf(padstack, "Smd_rect_%ldx%ld", &dim1l, &dim2l) == 2) { /* then pad is smd */ + dim1 = dim1l; + dim2 = dim2l; + pcb_fprintf(fp, + " (shape (rect \"%s\" %.6mm %.6mm %.6mm %.6mm))\n", + ((pcb_layer_t *) (g_list_first(layerlist)->data))->name, dim1 / -2, dim2 / -2, dim1 / 2, dim2 / 2); + } + else if (sscanf(padstack, "Th_square_%ld", &dim1l) == 1) { + dim1 = dim1l; + pcb_fprintf(fp, " (shape (rect signal %.6mm %.6mm %.6mm %.6mm))\n", dim1 / -2, dim1 / -2, dim1 / 2, dim1 / 2); + } + else { + sscanf(padstack, "Th_round_%ld", &dim1l); + dim1 = dim1l; + pcb_fprintf(fp, " (shape (circle signal %.6mm))\n", dim1); + } + fprintf(fp, " (attach off)\n"); + fprintf(fp, " )\n"); + } + + /* add padstack for via */ + pcb_fprintf(fp, " (padstack via_%ld_%ld\n", viawidth, viadrill); + pcb_fprintf(fp, " (shape (circle signal %.6mm))\n", viawidth); + pcb_fprintf(fp, " (attach off)\n )\n"); + + /* add padstack for terminals */ + pcb_fprintf(fp, "%s", term_shapes.array); + + pcb_fprintf(fp, " )\n"); + g_list_foreach(pads, (GFunc)free, NULL); + g_list_free(pads); + gds_uninit(&term_shapes); +} + +static void print_quoted_pin(FILE * fp, const char *s) +{ + char *hyphen_pos = strchr(s, '-'); + if (!hyphen_pos) { + fprintf(fp, " %s", s); + } + else { + char refdes_name[1024]; + int copy_len = hyphen_pos - s; + if (copy_len >= sizeof(refdes_name)) + copy_len = sizeof(refdes_name) - 1; + strncpy(refdes_name, s, copy_len); + refdes_name[copy_len] = 0; + fprintf(fp, " \"%s\"-\"%s\"", refdes_name, hyphen_pos + 1); + } +} + +static void print_network(FILE * fp) +{ + int ni, nei; + fprintf(fp, " (network\n"); + for (ni = 0; ni < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; ni++) { + fprintf(fp, " (net \"%s\"\n", PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[ni].Name + 2); + fprintf(fp, " (pins"); + for (nei = 0; nei < PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[ni].EntryN; nei++) + print_quoted_pin(fp, PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[ni].Entry[nei].ListEntry); + fprintf(fp, ")\n"); + fprintf(fp, " )\n"); + } + + fprintf(fp, " (class geda_default"); + for (ni = 0; ni < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; ni++) { + fprintf(fp, " \"%s\"", PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[ni].Name + 2); + } + 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) +{ + GList *iter; + pcb_layer_t *lay; + fprintf(fp, " (wiring\n"); + + for (iter = layerlist; iter; iter = g_list_next(iter)) { + lay = iter->data; + PCB_LINE_LOOP(lay); + { + pcb_fprintf(fp, + " (wire (path %s %.6mm %.6mm %.6mm %.6mm %.6mm)\n", + lay->name, 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 void dsn_parse_arguments(int *argc, char ***argv) +{ + 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) +{ + 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/1.2.7/src_plugins/export_dsn/export_dsn.pup =================================================================== --- tags/1.2.7/src_plugins/export_dsn/export_dsn.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_dsn/export_dsn.pup (revision 13657) @@ -0,0 +1,8 @@ +$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 elements (usable for freerouting) +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_dxf/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_dxf/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dxf + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_dxf/Makefile.test =================================================================== --- tags/1.2.7/src_plugins/export_dxf/Makefile.test (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/Makefile.test (revision 13657) @@ -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/1.2.7/src_plugins/export_dxf/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_dxf/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_dxf/dxf.c =================================================================== --- tags/1.2.7/src_plugins/export_dxf/dxf.c (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/dxf.c (revision 13657) @@ -0,0 +1,516 @@ + /* + * 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. + * + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "error.h" +#include "layer.h" +#include "plugins.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "lht_template.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_helper.h" +#include "hid_flags.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"; + +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_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 = { + 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 + +}; + +#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) +{ + static char *last_made_filename = 0; + const char *suffix = ".dxf"; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &dxf_attribute_list[HA_dxffile], suffix, &last_made_filename); + + 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); + + 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; + } + + filename = options[HA_dxffile].str_value; + if (!filename) + filename = "pcb.dxf"; + + dxf_ctx.f = pcb_fopen(filename, "wb"); + if (!dxf_ctx.f) { + perror(filename); + return; + } + + 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 (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"); + + pcb_hid_save_and_show_layer_ons(save_ons); + + dxf_hid_export_to_file(&dxf_ctx, options); + + 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); +} + +static void 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); + pcb_hid_parse_command_line(argc, argv); +} + +static int dxf_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_INVIS) + return 0; + + dxf_ctx.force_thin = 0; + + if (flags & PCB_LYT_OUTLINE) { + dxf_ctx.layer_name = "outline"; + dxf_ctx.force_thin = 1; + return 1; + } + + if (flags & PCB_LYT_PDRILL) { + dxf_ctx.layer_name = "drill_plated"; + dxf_ctx.force_thin = 1; + return 1; + } + + if (flags & PCB_LYT_UDRILL) { + 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_NEGATIVE: + break; + + case PCB_HID_COMP_FLUSH: + break; + } +} + +static void dxf_set_color(pcb_hid_gc_t gc, const char *name) +{ + if (strcmp(name, "drill") == 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(int x, int 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) +{ + 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.holes_after = 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/1.2.7/src_plugins/export_dxf/dxf_draw.c =================================================================== --- tags/1.2.7/src_plugins/export_dxf/dxf_draw.c (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/dxf_draw.c (revision 13657) @@ -0,0 +1,208 @@ + /* + * 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. + * + */ + +#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; + + if (delta_angle > 0) { + end_angle = start_angle-delta_angle; + start_angle -= 90; + end_angle -= 90; + + if (end_angle >= 360) + end_angle -= 360; + if (end_angle < 0) + end_angle += 360; + + tmp = start_angle; + start_angle = end_angle; + end_angle = tmp; + } + else { + end_angle = start_angle-delta_angle; + start_angle += 90; + end_angle += 90; + + 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/1.2.7/src_plugins/export_dxf/dxf_templ.lht =================================================================== --- tags/1.2.7/src_plugins/export_dxf/dxf_templ.lht (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/dxf_templ.lht (revision 13657) @@ -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/1.2.7/src_plugins/export_dxf/export_dxf.pup =================================================================== --- tags/1.2.7/src_plugins/export_dxf/export_dxf.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/export_dxf.pup (revision 13657) @@ -0,0 +1,8 @@ +$class export +$short DXF pcb_exporter +$long Export dxf +$state works +$fmt-native no +$fmt-feature-w export to 2D .dxf (for mech CADs) +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_dxf/lht_template.c =================================================================== --- tags/1.2.7/src_plugins/export_dxf/lht_template.c (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/lht_template.c (revision 13657) @@ -0,0 +1,125 @@ + /* + * 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. + * + */ + +/* 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/1.2.7/src_plugins/export_dxf/lht_template.h =================================================================== --- tags/1.2.7/src_plugins/export_dxf/lht_template.h (nonexistent) +++ tags/1.2.7/src_plugins/export_dxf/lht_template.h (revision 13657) @@ -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/1.2.7/src_plugins/export_fidocadj/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_fidocadj/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_fidocadj/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_fidocadj + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_fidocadj/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_fidocadj/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_fidocadj/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_fidocadj/export_fidocadj.pup =================================================================== --- tags/1.2.7/src_plugins/export_fidocadj/export_fidocadj.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_fidocadj/export_fidocadj.pup (revision 13657) @@ -0,0 +1,8 @@ +$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 +default disable-all +autoload 1 Index: tags/1.2.7/src_plugins/export_fidocadj/fidocadj.c =================================================================== --- tags/1.2.7/src_plugins/export_fidocadj/fidocadj.c (nonexistent) +++ tags/1.2.7/src_plugins/export_fidocadj/fidocadj.c (revision 13657) @@ -0,0 +1,364 @@ + /* + * COPYRIGHT + * + * 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. + * + */ + +/* + * 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 "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_helper.h" +#include "hid_flags.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) +{ + static char *last_made_filename = 0; + const char *suffix = ".fcd"; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &fidocadj_attribute_list[HA_fidocadjfile], suffix, &last_made_filename); + + 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, int *warned, 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) { + if (!*warned) + pcb_message(PCB_MSG_ERROR, "FidoCadJ can't handle this many layers - layer %s is not exported\n", lyname); + *warned = 1; + return -1; + } + return *fidoly_next; +} + +static void write_custom_element(FILE *f, pcb_element_t *e) +{ + pcb_message(PCB_MSG_ERROR, "Can't export custom footprint for %s yet\n", e->Name[PCB_ELEMNAME_IDX_REFDES].TextString); +} + +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; + int layer_warned = 0, hole_warned = 0; + 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, &layer_warned, 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) { +#warning 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) { + if (!hole_warned) + pcb_message(PCB_MSG_ERROR, "FidoCadJ can't handle holes in polygons, ignoring holes for this export - some of the polygons will look different\n"); + hole_warned = 1; + } + + 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; + }*/ + fprintf(f, "TY %ld %ld %ld %ld %d 1 %d * ", /* 1 = bold */ + crd(x0), crd(y0), crd(glyphy), crd(glyphx), + 90*(text->Direction), fidoly); + for(s = text->TextString; *s != '\0'; s++) { + if (*s == ' ') + fprintf(f, "++"); + else + fputc(*s, f); + } + fputc('\n', f); + } + PCB_END_LOOP; + } + + PCB_VIA_LOOP(PCB->Data) { + fprintf(f, "pa %ld %ld", crd(via->X), crd(via->Y)); + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, via)) { + if (!((PCB_FLAG_SQUARE_GET(via) == 0) || (PCB_FLAG_SQUARE_GET(via) == 1))) { +#warning TODO: find out the orientation + fprintf(f, "%ld %ld %ld 2\n", crd(via->Thickness), crd(via->Thickness*2), crd(via->DrillingHole)); /* rounded corner rectangle */ + } + else + fprintf(f, "%ld %ld %ld 1\n", crd(via->Thickness), crd(via->Thickness), crd(via->DrillingHole)); /* rectangle with sharp corners */ + } + else + fprintf(f, "%ld %ld %ld 0\n", crd(via->Thickness), crd(via->Thickness), crd(via->DrillingHole)); /* circular */ + } + PCB_END_LOOP; + + PCB_ELEMENT_LOOP(PCB->Data) { + const char *fp = element->Name[PCB_ELEMNAME_IDX_DESCRIPTION].TextString; + if (have_lib && (htsi_get(&lib_names, fp))) + fprintf(f, "MC %ld %ld %d 0 %s\n", crd(element->MarkX), crd(element->MarkY), 0, fp); + else + write_custom_element(f, element); + } + 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 void 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); + 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) +{ +} + +int pplg_init_export_fidocadj(void) +{ + 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/1.2.7/src_plugins/export_gcode/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_gcode/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gcode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_gcode/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_gcode/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/auxiliary.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/auxiliary.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/auxiliary.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/bitmap.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/bitmap.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/bitmap.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/curve.c =================================================================== --- tags/1.2.7/src_plugins/export_gcode/curve.c (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/curve.c (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/curve.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/curve.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/curve.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/decompose.c =================================================================== --- tags/1.2.7/src_plugins/export_gcode/decompose.c (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/decompose.c (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/decompose.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/decompose.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/decompose.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/export_gcode.pup =================================================================== --- tags/1.2.7/src_plugins/export_gcode/export_gcode.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/export_gcode.pup (revision 13657) @@ -0,0 +1,8 @@ +$class export +$short gcode pcb_exporter +$long Export to gcode +$state works +$fmt-native no +$fmt-feature-w export gcode (for milling) +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_gcode/gcode.c =================================================================== --- tags/1.2.7/src_plugins/export_gcode/gcode.c (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/gcode.c (revision 13657) @@ -0,0 +1,928 @@ +/* + * COPYRIGHT + * + * 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. + * + */ + +/* + * 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 "rats.h" +#include "hid_helper.h" +#include "layer.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 "hid_init.h" +#include "hid_attrib.h" +#include "hid_flags.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_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 void 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); + pcb_hid_parse_command_line(argc, argv); +} + +static pcb_hid_attribute_t *gcode_get_export_options(int *n) +{ + static char *last_made_filename = 0; + 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) { + pcb_derive_default_filename(PCB->Filename, &gcode_attribute_list[HA_basename], ".gcode", &last_made_filename); + } + 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 */ + + /* + * is this check necessary? It seems that special + * layers have negative indexes? + */ + + if ((flags & PCB_LYT_COPPER) || (flags & PCB_LYT_OUTLINE)) { + 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); +} + +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 = &(get_unit_list()[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_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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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 = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + 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 = Trace_Cap; + 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 char *name) +{ + if (gcode_im == NULL) { + return; + } + if (name == NULL) { + name = "#ff0000"; + } + if (!strcmp(name, "drill")) { + gc->color = black; + gc->erase = 0; + return; + } + if (!strcmp(name, "erase")) { + /* FIXME -- should be background, not white */ + gc->color = white; + gc->erase = 1; + 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 Round_Cap: + case Trace_Cap: + type = 'C'; + r = pcb_to_gcode(gc->width / 2 + gcode_toolradius); + break; + default: + case Square_Cap: + r = pcb_to_gcode(gc->width + gcode_toolradius * 2); + type = 'S'; + break; + } + 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(int x, int 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) +{ + 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/1.2.7/src_plugins/export_gcode/gcode.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/gcode.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/gcode.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/lists.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/lists.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/lists.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/potracelib.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/potracelib.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/potracelib.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/trace.c =================================================================== --- tags/1.2.7/src_plugins/export_gcode/trace.c (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/trace.c (revision 13657) @@ -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/1.2.7/src_plugins/export_gcode/trace.h =================================================================== --- tags/1.2.7/src_plugins/export_gcode/trace.h (nonexistent) +++ tags/1.2.7/src_plugins/export_gcode/trace.h (revision 13657) @@ -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/1.2.7/src_plugins/export_gerber/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_gerber/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_gerber/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gerber + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_gerber/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_gerber/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_gerber/Plug.tmpasm (revision 13657) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_gerber} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_gerber/gerber.o @] + +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/1.2.7/src_plugins/export_gerber/export_gerber.pup =================================================================== --- tags/1.2.7/src_plugins/export_gerber/export_gerber.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_gerber/export_gerber.pup (revision 13657) @@ -0,0 +1,8 @@ +$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) +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_gerber/gerber.c =================================================================== --- tags/1.2.7/src_plugins/export_gerber/gerber.c (nonexistent) +++ tags/1.2.7/src_plugins/export_gerber/gerber.c (revision 13657) @@ -0,0 +1,1320 @@ +#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 "pcb-printf.h" +#include "plugins.h" +#include "hid_helper.h" +#include "compat_misc.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_flags.h" +#include "conf_core.h" + +const char *gerber_cookie = "gerber HID"; + +#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_hid_attribute_t *gerber_get_export_options(int *n); +static void gerber_do_export(pcb_hid_attr_val_t * options); +static void 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 char *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(int x, int 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))) + +/* Note: these are for drills (printed as mils but are really 1/10th mil) so print them with %mk */ +#define gerberDrX(pcb, x) ((pcb_coord_t) (x)) +#define gerberDrY(pcb, y) ((pcb_coord_t) ((pcb)->MaxHeight - (y))) + +/*----------------------------------------------------------------------------*/ +/* Private data structures */ +/*----------------------------------------------------------------------------*/ + +static int verbose; +static int all_layers; +static int is_mask, was_drill; +static int is_drill; +static pcb_composite_op_t gerber_drawing_mode, drawing_mode_issued; +static int flash_drills; +static int copy_outline_mode; +static int name_style; +static int want_cross_sect; +static pcb_layer_t *outline_layer; +static int gerber_debug; + +enum ApertureShape { + ROUND, /* Shaped like a circle */ + OCTAGON, /* octagonal shape */ + SQUARE /* Shaped like a square */ +}; +typedef enum ApertureShape ApertureShape; + +/* 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 */ + ApertureShape shape; /* ROUND/SQUARE etc */ + struct aperture *next; +} Aperture; + +typedef struct { + Aperture *data; + int count; +} ApertureList; + +static ApertureList *layer_aptr_list; +static ApertureList *curr_aptr_list; +static int layer_list_max; +static int layer_list_idx; + +typedef struct { + pcb_coord_t diam; + pcb_coord_t x; + pcb_coord_t y; +} PendingDrills; +PendingDrills *pending_drills = NULL; +int n_pending_drills = 0, max_pending_drills = 0; + +/*----------------------------------------------------------------------------*/ +/* Defined Constants */ +/*----------------------------------------------------------------------------*/ +#define AUTO_OUTLINE_WIDTH PCB_MIL_TO_COORD(8) /* Auto-geneated outline width of 8 mils */ + +/*----------------------------------------------------------------------------*/ +/* Aperture Routines */ +/*----------------------------------------------------------------------------*/ + +/* Initialize aperture list */ +static void initApertureList(ApertureList * list) +{ + list->data = NULL; + list->count = 0; +} + +static void deinitApertureList(ApertureList * list) +{ + Aperture *search = list->data; + Aperture *next; + while (search) { + next = search->next; + free(search); + search = next; + } + initApertureList(list); +} + +static void resetApertures() +{ + int i; + for (i = 0; i < layer_list_max; ++i) + deinitApertureList(&layer_aptr_list[i]); + free(layer_aptr_list); + layer_aptr_list = NULL; + curr_aptr_list = NULL; + layer_list_max = 0; + layer_list_idx = 0; +} + +/* Create and add a new aperture to the list */ +static Aperture *addAperture(ApertureList * list, pcb_coord_t width, ApertureShape shape) +{ + static int aperture_count; + + Aperture *app = (Aperture *) 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; +} + +/* Fetch an aperture from the list with the specified + * width/shape, creating a new one if none exists */ +static Aperture *findAperture(ApertureList * list, pcb_coord_t width, ApertureShape shape) +{ + Aperture *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 addAperture(list, width, shape); +} + +/* Output aperture data to the file */ +static void fprintAperture(FILE * f, Aperture * aptr) +{ + switch (aptr->shape) { + case ROUND: + pcb_fprintf(f, "%%ADD%dC,%.4mi*%%\r\n", aptr->dCode, aptr->width); + break; + case SQUARE: + pcb_fprintf(f, "%%ADD%dR,%.4miX%.4mi*%%\r\n", aptr->dCode, aptr->width, aptr->width); + break; + case OCTAGON: + pcb_fprintf(f, "%%AMOCT%d*5,0,8,0,0,%.4mi,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; + } +} + +/* Set the aperture list for the current layer, + * expanding the list buffer if needed */ +static ApertureList *setLayerApertureList(int layer_idx) +{ + if (layer_idx >= layer_list_max) { + int i = layer_list_max; + layer_list_max = 2 * (layer_idx + 1); + layer_aptr_list = (ApertureList *) + realloc(layer_aptr_list, layer_list_max * sizeof(*layer_aptr_list)); + for (; i < layer_list_max; ++i) + initApertureList(&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_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_FIXED 0 + "fixed", +#define NAME_STYLE_SINGLE 1 + "single", +#define NAME_STYLE_FIRST 2 + "first", +#define NAME_STYLE_EAGLE 3 + "eagle", +#define NAME_STYLE_HACKVANA 4 + "hackvana", +#define NAME_STYLE_UNIVERSAL 5 + "universal", + 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 +}; + +#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) +{ + static char *last_made_filename = NULL; + if (PCB) + pcb_derive_default_filename(PCB->Filename, &gerber_options[HA_gerberfile], "", &last_made_filename); + + 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) + 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) +{ + 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 (fmatch(flags, PCB_LYT_PDRILL)) + suff = "drd"; + else if (fmatch(flags, PCB_LYT_UDRILL)) + 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 (fmatch(flags, PCB_LYT_FAB)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_ASSY)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_ASSY)) + suff = "asb"; + else if (fmatch(flags, PCB_LYT_OUTLINE)) + 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) +{ + 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 (fmatch(flags, PCB_LYT_PDRILL)) + suff = "drl"; + else if (fmatch(flags, PCB_LYT_UDRILL)) + 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 (fmatch(flags, PCB_LYT_FAB)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_ASSY)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_ASSY)) + suff = "asb"; + else if (fmatch(flags, PCB_LYT_OUTLINE)) + 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) +{ + 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 (fmatch(flags, PCB_LYT_PDRILL)) + suff = "drl"; + else if (fmatch(flags, PCB_LYT_UDRILL)) + 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 (fmatch(flags, PCB_LYT_FAB)) + suff = "fab"; + else if (fmatch(flags, PCB_LYT_TOP | PCB_LYT_ASSY)) + suff = "ast"; + else if (fmatch(flags, PCB_LYT_BOTTOM | PCB_LYT_ASSY)) + suff = "asb"; + else if (fmatch(flags, PCB_LYT_OUTLINE)) + 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) +{ + int fns_style; + const char *sext = ".gbr"; + + switch (name_style) { + default: + 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); + return; + case NAME_STYLE_HACKVANA: + assign_hackvana_file_suffix(dest, lid, flags); + return; + case NAME_STYLE_UNIVERSAL: + assign_universal_file_suffix(dest, gid, flags); + return; + } + + if ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)) + sext = ".cnc"; + pcb_layer_to_file_name(dest, lid, flags, 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); + + 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; + } + + fnbase = options[HA_gerberfile].str_value; + if (!fnbase) + fnbase = "pcb-out"; + + verbose = options[HA_verbose].int_value; + 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; + +#warning layer TODO: this assumes there is only one outline layer; instead of this, just use a boolthat says whether we had an outline layer and redo the search + outline_layer = NULL; + + for (i = 0; i < pcb_max_layer; i++) + if (pcb_layer_flags(PCB, i) & PCB_LYT_OUTLINE) + outline_layer = PCB->Data->Layer + i; + + i = strlen(fnbase); + filename = (char *) realloc(filename, i + SUFF_LEN); + strcpy(filename, fnbase); + strcat(filename, "."); + filesuff = filename + strlen(filename); + + 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; + resetApertures(); + + lastgroup = -1; + layer_list_idx = 0; + finding_apertures = 1; + pcb_hid_expose_all(&gerber_hid, &ctx); + + layer_list_idx = 0; + finding_apertures = 0; + pcb_hid_expose_all(&gerber_hid, &ctx); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + + maybe_close_f(f); + f = NULL; + pcb_hid_restore_layer_ons(save_ons); + conf_update(NULL, -1); /* resotre forced sets */ +} + +static void gerber_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(gerber_options, NUM_OPTIONS, gerber_cookie, 0); + pcb_hid_parse_command_line(argc, argv); +} + +static int drill_sort(const void *va, const void *vb) +{ + PendingDrills *a = (PendingDrills *) va; + PendingDrills *b = (PendingDrills *) 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; +} + +static int gerber_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + int want_outline; + char *cp; + const char *group_name; + + 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) + if ((group >= 0) && pcb_layergrp_is_empty(PCB, group) && !(flags & PCB_LYT_SILK)) + return 0; + + if ((flags & PCB_LYT_INVIS) || (flags & PCB_LYT_ASSY)) { +/* printf(" nope: invis %d or assy %d\n", (flags & PCB_LYT_INVIS), (flags & PCB_LYT_ASSY));*/ + return 0; + } + + if ((flags & PCB_LYT_CSECT) && (!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; + if (flags & PCB_LYT_OUTLINE) + flash_drills = 1; + + if (is_drill && n_pending_drills) { + int i; + /* dump pending drills in sequence */ + qsort(pending_drills, n_pending_drills, sizeof(pending_drills[0]), drill_sort); + for (i = 0; i < n_pending_drills; i++) { + if (i == 0 || pending_drills[i].diam != pending_drills[i - 1].diam) { + Aperture *ap = findAperture(curr_aptr_list, pending_drills[i].diam, ROUND); + fprintf(f, "T%02d\r\n", ap->dCode); + } + pcb_fprintf(f, "X%06.0mkY%06.0mk\r\n", gerberDrX(PCB, pending_drills[i].x), gerberDrY(PCB, pending_drills[i].y)); + } + free(pending_drills); + n_pending_drills = max_pending_drills = 0; + pending_drills = NULL; + } + + is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + is_mask = !!(flags & PCB_LYT_MASK); + if (group < 0 || group != lastgroup) { + char utcTime[64]; + ApertureList *aptr_list; + Aperture *search; + + lastgroup = group; + lastX = -1; + lastY = -1; + lastcolor = 0; + linewidth = -1; + lastcap = -1; + + aptr_list = setLayerApertureList(layer_list_idx++); + + if (finding_apertures) + goto emit_outline; + + if (aptr_list->count == 0 && !all_layers) + return 0; + + maybe_close_f(f); + f = NULL; + + pagecount++; + assign_file_suffix(filesuff, group, layer, flags); + f = pcb_fopen(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; + printf("Gerber: %d aperture%s in %s\n", c, c == 1 ? "" : "s", filename); + } + + if (is_drill) { + /* 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 = aptr_list->data; search; search = search->next) + pcb_fprintf(f, "T%02dC%.3mi\r\n", search->dCode, search->width); + fprintf(f, "%%\r\n"); + /* FIXME */ + return 1; + } + + 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: %.0mc %.0mc *\r\n", PCB->MaxWidth, PCB->MaxHeight); + fprintf(f, "G04 PCB-Coordinate-Origin: lower left *\r\n"); + + /* Signal data in inches. */ + fprintf(f, "%%MOIN*%%\r\n"); + + /* Signal Leading zero suppression, Absolute Data, 2.5 format */ + fprintf(f, "%%FSLAX25Y25*%%\r\n"); + + /* 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) + fprintAperture(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) || (flags & PCB_LYT_FAB) || (flags & PCB_LYT_ASSY))) + want_outline = 1; + + if (want_outline && !(flags & PCB_LYT_OUTLINE)) { + if (outline_layer && outline_layer != PCB->Data->Layer + layer) + pcb_draw_layer(outline_layer, ®ion); + else if (!outline_layer) { + pcb_hid_gc_t gc = pcb_gui->make_gc(); + if (flags & PCB_LYT_SILK) + pcb_gui->set_line_width(gc, PCB->minSlk); + else if (group >= 0) + pcb_gui->set_line_width(gc, PCB->minWid); + else + pcb_gui->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_gui->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 = Trace_Cap; + 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 char *name) +{ + if (strcmp(name, "erase") == 0) { + gc->color = 1; + gc->erase = 1; + gc->drill = 0; + } + else if (strcmp(name, "drill") == 0) { + 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) { + 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 != Round_Cap) { + Aperture *aptr = findAperture(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 && !is_drill) + fprintf(f, "G54D%d*", aptr->dCode); + linewidth = radius; + lastcap = Round_Cap; + } + } + else if (linewidth != gc->width || lastcap != gc->cap) { + Aperture *aptr; + ApertureShape shape; + + linewidth = gc->width; + lastcap = gc->cap; + switch (gc->cap) { + case Round_Cap: + case Trace_Cap: + shape = ROUND; + break; + default: + case Square_Cap: + shape = SQUARE; + break; + } + aptr = findAperture(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); + } + + +#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 (x1 != x2 && y1 != y2 && gc->cap == Square_Cap) { + 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%.0mc", gerberX(PCB, lastX)); + } + if (y1 != lastY) { + m = pcb_true; + lastY = y1; + pcb_fprintf(f, "Y%.0mc", 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%.0mc", gerberX(PCB, lastX)); + } + if (y2 != lastY) { + lastY = y2; + pcb_fprintf(f, "Y%.0mc", 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%.0mc", gerberX(PCB, lastX)); + } + if (arcStartY != lastY) { + m = pcb_true; + lastY = arcStartY; + pcb_fprintf(f, "Y%.0mc", gerberY(PCB, lastY)); + } + if (m) + fprintf(f, "D02*"); + pcb_fprintf(f, + "G75*G0%1dX%.0mcY%.0mcI%.0mcJ%.0mcD01*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 (n_pending_drills >= max_pending_drills) { + max_pending_drills += 100; + pending_drills = (PendingDrills *) realloc(pending_drills, max_pending_drills * sizeof(pending_drills[0])); + } + pending_drills[n_pending_drills].x = cx; + pending_drills[n_pending_drills].y = cy; + pending_drills[n_pending_drills].diam = radius * 2; + n_pending_drills++; + return; + } + else if (gc->drill && !flash_drills) + return; + if (cx != lastX) { + lastX = cx; + pcb_fprintf(f, "X%.0mc", gerberX(PCB, lastX)); + } + if (cy != lastY) { + lastY = cy; + pcb_fprintf(f, "Y%.0mc", 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 (is_mask && (gerber_drawing_mode != PCB_HID_COMP_POSITIVE) && (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%.0mc", gerberX(PCB, lastX)); + } + if (y[i]+dy != lastY) { + m = pcb_true; + lastY = y[i]+dy; + pcb_fprintf(f, "Y%.0mc", 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%.0mc", gerberX(PCB, startX)); + } + if (startY != lastY) { + m = pcb_true; + lastY = startY; + pcb_fprintf(f, "Y%.0mc", 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(int x, int 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); +} + +int pplg_init_export_gerber(void) +{ + 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 0; +} Index: tags/1.2.7/src_plugins/export_ipcd356/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_ipcd356/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_ipcd356/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ipcd356 + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_ipcd356/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_ipcd356/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_ipcd356/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_ipcd356/export_ipcd356.pup =================================================================== --- tags/1.2.7/src_plugins/export_ipcd356/export_ipcd356.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_ipcd356/export_ipcd356.pup (revision 13657) @@ -0,0 +1,8 @@ +$class export +$short IPC-D-356 Netlist pcb_exporter +$long IPC-D-356 Netlist export. +$state Work-in-progress +$fmt-native no +$fmt-feature-w export IPC-D-356 Netlist (for automated testing) +default disable-all +autoload 1 Index: tags/1.2.7/src_plugins/export_ipcd356/ipcd356.c =================================================================== --- tags/1.2.7/src_plugins/export_ipcd356/ipcd356.c (nonexistent) +++ tags/1.2.7/src_plugins/export_ipcd356/ipcd356.c (revision 13657) @@ -0,0 +1,627 @@ +/* + * + * IPC-D-356 Netlist export. + * + * Copyright (C) 2012 Jerome Marchand (Jerome.Marchand@gmail.com) + * + * PCB, interactive printed circuit board design + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have 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 addresses for paper mail and Email: + * + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * + * Thomas.Nau@rz.uni-ulm.de + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "board.h" +#include "data.h" +#include "rats.h" +#include "error.h" +#include "find.h" +#include "pcb-printf.h" +#include "netlist.h" +#include "conf_core.h" +#include "obj_pinvia.h" +#include "compat_misc.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_helper.h" +#include "hid_attrib.h" +#include "hid_init.h" +#include "plugins.h" + +static const char *ipcd356_cookie = "ipcd356 exporter"; + +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]; + +const char *IPCD356_filename; + +typedef struct { + char NName[11]; + char NetName[256]; +} IPCD356_Alias; + +typedef struct { + int AliasN; /*!< Number of entries. */ + IPCD356_Alias *Alias; +} IPCD356_AliasList; + +void IPCD356_WriteNet(FILE *, char *); +void IPCD356_WriteHeader(FILE *); +void IPCD356_End(FILE *); +int IPCD356_Netlist(void); +int IPCD356_WriteAliases(FILE *, IPCD356_AliasList *); +void ResetVisitPinsViasAndPads(void); +void CheckNetLength(char *, IPCD356_AliasList *); +IPCD356_AliasList *CreateAliasList(void); +IPCD356_AliasList *AddAliasToList(IPCD356_AliasList *); +int IPCD356_SanityCheck(void); + +static pcb_hid_attribute_t *IPCD356_get_export_options(int *n) +{ + static char *last_IPCD356_filename = 0; + + if (PCB) { + pcb_derive_default_filename(PCB->Filename, &IPCD356_options[HA_IPCD356_filename], ".net", &last_IPCD356_filename); + } + + if (n) + *n = NUM_OPTIONS; + + return IPCD356_options; +} + +/*! + * \brief Writes the IPC-D-356 Header to the file provided. + * + * The JOB name is the PCB Name (if set), otherwise the filename + * (including the path) is used. + * + * The units used for the netlist depends on what is set (mils or mm). + */ +void IPCD356_WriteHeader(FILE * fd) +{ + char utcTime[64]; + + pcb_print_utc(utcTime, sizeof utcTime, 0); + + fprintf(fd, "C IPC-D-356 Netlist generated by pcb-rnd " PCB_VERSION "\nC \n"); + fprintf(fd, "C File created on %s\nC \n", utcTime); + if (PCB->Name == NULL) { + fprintf(fd, "P JOB %s\n", PCB->Filename); /* Use the file name if the PCB name in not set. */ + } + else { + fprintf(fd, "P JOB %s\n", PCB->Name); + } + fprintf(fd, "P CODE 00\n"); + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { /* Use whatever unit is currently in use (mil or mm). */ + fprintf(fd, "P UNITS CUST 0\n"); + } + else { + fprintf(fd, "P UNITS CUST 1\n"); + } + fprintf(fd, "P DIM N\n"); + fprintf(fd, "P VER IPC-D-356\n"); + fprintf(fd, "P IMAGE PRIMARY\nC \n"); +} + + +/*! + * \brief Writes a net to the file provided. + * + * The net name is passed through the "net" and should be 14 characters + * max.\n + * The function scans through pads, pins and vias and looks for the + * \c PCB_FLAG_FOUND.\n + * Once the object has been added to the net list the \c PCB_FLAG_VISIT is + * set on that object. + * + * \todo 1) The bottom layer is always written as layer #2 (A02).\n + * It could output the actual layer number (example: A06 on a + * 6 layer board).\n + * But I could not find an easy way to do this... + * + * \todo 2) Objects with mutiple connections could have the "M" + * (column 32) field written to indicate a Mid Net Point. + */ +void IPCD356_WriteNet(FILE * fd, char *net) +{ + int padx, pady, tmp; + + PCB_ELEMENT_LOOP(PCB->Data); + PCB_PAD_LOOP(element); + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, pad)) { + fprintf(fd, "327%-17.14s", net); /* Net Name. */ + fprintf(fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ + fprintf(fd, "-%-4.4s", pad->Number); /* pin number. */ + fprintf(fd, " "); /*! \todo Midpoint indicator (M). */ + fprintf(fd, " "); /* Drilled hole Id (blank for pads). */ + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) == pcb_true) { + fprintf(fd, "A02"); /*! \todo Put actual layer # for bottom side. */ + } + else { + fprintf(fd, "A01"); /* Top side. */ + } + padx = (pad->Point1.X + pad->Point2.X) / 2; /* X location in PCB units. */ + pady = (PCB->MaxHeight - ((pad->Point1.Y + pad->Point2.Y) / 2)); /* Y location in PCB units. */ + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + pady = pady / 2540; /* Y location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001 mm. */ + pady = pady / 1000; /* Y location in 0.001 mm. */ + } + fprintf(fd, "X%+6.6d", padx); /* X Pad center. */ + fprintf(fd, "Y%+6.6d", pady); /* Y pad center. */ + + padx = (pad->Thickness + (pad->Point2.X - pad->Point1.X)); /* Pad dimension X in PCB units. */ + pady = (pad->Thickness + (pad->Point2.Y - pad->Point1.Y)); /* Pad dimension Y in PCB units. */ + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + pady = pady / 2540; /* Y location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001mm */ + pady = pady / 1000; /* Y location in 0.001mm */ + } + + fprintf(fd, "X%4.4d", padx); + fprintf(fd, "Y%4.4d", pady); + fprintf(fd, "R000"); /* Rotation (0 degrees). */ + fprintf(fd, " "); /* Column 72 should be left blank. */ + if (pad->Mask > 0) { + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) == pcb_true) { + fprintf(fd, "S2"); /* Soldermask on bottom side. */ + } + else { + fprintf(fd, "S1"); /* SolderMask on top side. */ + } + } + else { + fprintf(fd, "S3"); /* No soldermask. */ + } + fprintf(fd, " "); /* Padding. */ + fprintf(fd, "\n"); + PCB_FLAG_SET(PCB_FLAG_VISIT, pad); + } + + PCB_END_LOOP; /* Pad. */ + PCB_PIN_LOOP(element); + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, pin)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { /* Non plated? */ + fprintf(fd, "367%-17.14s", net); /* Net Name. */ + } + else { + fprintf(fd, "317%-17.14s", net); /* Net Name. */ + } + fprintf(fd, "%-6.6s", element->Name[1].TextString); /* Refdes. */ + fprintf(fd, "-%-4.4s", pin->Number); /* Pin number. */ + fprintf(fd, " "); /*! \todo Midpoint indicator (M). */ + tmp = pin->DrillingHole; + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + tmp = tmp / 2540; /* 0.0001". */ + } + else { + tmp = tmp / 1000; /* 0.001 mm. */ + } + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) { + fprintf(fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ + } + else { + fprintf(fd, "D%-4.4dP", tmp); /* Plated drill hole. */ + } + fprintf(fd, "A00"); /* Accessible from both sides. */ + padx = pin->X; /* X location in PCB units. */ + pady = (PCB->MaxHeight - pin->Y); /* Y location in PCB units. */ + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + pady = pady / 2540; /* Y location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001 mm. */ + pady = pady / 1000; /* Y location in 0.001 mm. */ + } + + fprintf(fd, "X%+6.6d", padx); /* X Pad center. */ + fprintf(fd, "Y%+6.6d", pady); /* Y pad center. */ + + padx = pin->Thickness; + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001 mm. */ + } + + fprintf(fd, "X%4.4d", padx); /* Pad dimension X. */ + if (PCB_FLAG_TEST(PCB_FLAG_SQUARE, pin)) { + fprintf(fd, "Y%4.4d", padx); /* Pad dimension Y. */ + } + else { + fprintf(fd, "Y0000"); /* Y is 0 for round pins. */ + } + fprintf(fd, "R000"); /* Rotation (0 degrees). */ + fprintf(fd, " "); /* Column 72 should be left blank. */ + if (pin->Mask > 0) { + fprintf(fd, "S0"); /* No Soldermask. */ + } + else { + fprintf(fd, "S3"); /* Soldermask on both sides. */ + } + fprintf(fd, " "); /* Padding. */ + + fprintf(fd, "\n"); + + PCB_FLAG_SET(PCB_FLAG_VISIT, pin); + + } + + PCB_END_LOOP; /* Pin. */ + PCB_END_LOOP; /* Element */ + + PCB_VIA_LOOP(PCB->Data); + if (PCB_FLAG_TEST(PCB_FLAG_FOUND, via)) { + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, via)) { /* Non plated ? */ + fprintf(fd, "367%-17.14s", net); /* Net Name. */ + } + else { + fprintf(fd, "317%-17.14s", net); /* Net Name. */ + } + fprintf(fd, "VIA "); /* Refdes. */ + fprintf(fd, "- "); /* Pin number. */ + fprintf(fd, " "); /*! \todo Midpoint indicator (M). */ + tmp = via->DrillingHole; + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + tmp = tmp / 2540; /* 0.0001". */ + } + else { + tmp = tmp / 1000; /* 0.001 mm. */ + } + + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, via)) { + fprintf(fd, "D%-4.4dU", tmp); /* Unplated Drilled hole Id. */ + } + else { + fprintf(fd, "D%-4.4dP", tmp); /* Plated drill hole. */ + } + fprintf(fd, "A00"); /* Accessible from both sides. */ + padx = via->X; /* X location in PCB units. */ + pady = (PCB->MaxHeight - via->Y); /* Y location in PCB units. */ + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + pady = pady / 2540; /* Y location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001 mm. */ + pady = pady / 1000; /* Y location in 0.001 mm. */ + } + + fprintf(fd, "X%+6.6d", padx); /* X Pad center. */ + fprintf(fd, "Y%+6.6d", pady); /* Y pad center. */ + + padx = via->Thickness; + + if (strcmp(conf_core.editor.grid_unit->suffix, "mil") == 0) { + padx = padx / 2540; /* X location in 0.0001". */ + } + else { + padx = padx / 1000; /* X location in 0.001 mm. */ + } + + fprintf(fd, "X%4.4d", padx); /* Pad dimension X. */ + fprintf(fd, "Y0000"); /* Y is 0 for round pins (vias always round?). */ + fprintf(fd, "R000"); /* Rotation (0 degrees). */ + fprintf(fd, " "); /* Column 72 should be left blank. */ + if (via->Mask > 0) { + fprintf(fd, "S0"); /* No Soldermask. */ + } + else { + fprintf(fd, "S3"); /* Soldermask on both sides. */ + } + fprintf(fd, " "); /* Padding. */ + fprintf(fd, "\n"); + PCB_FLAG_SET(PCB_FLAG_VISIT, via); + } + + PCB_END_LOOP; /* Via. */ +} + + +/*! + * \brief The main IPC-D-356 function. + * + * Gets the filename for the netlist from the dialog. + */ +int IPCD356_Netlist(void) +{ + FILE *fp; + char nodename[256]; + char net[256]; + pcb_lib_menu_t *netname; + IPCD356_AliasList *aliaslist; + + if (IPCD356_SanityCheck()) { /* Check for invalid names + numbers. */ + pcb_message(PCB_MSG_ERROR, "IPCD356: aborting on the sanity check.\n"); + return (1); + } + + sprintf(net, "%s.ipc", PCB->Name); + if (IPCD356_filename == NULL) + return 1; + + fp = pcb_fopen(IPCD356_filename, "w+"); + if (fp == NULL) { + pcb_message(PCB_MSG_ERROR, "error opening %s\n", IPCD356_filename); + return 1; + } +/* free (IPCD356_filename); */ + + + IPCD356_WriteHeader(fp); + + aliaslist = CreateAliasList(); + if (aliaslist == NULL) { + pcb_message(PCB_MSG_ERROR, "Error Aloccating memory for IPC-D-356 AliasList\n"); + return 1; + } + + if (IPCD356_WriteAliases(fp, aliaslist)) { + pcb_message(PCB_MSG_ERROR, "Error Writing IPC-D-356 AliasList\n"); + return 1; + } + + + PCB_ELEMENT_LOOP(PCB->Data); + PCB_PIN_LOOP(element); + if (!PCB_FLAG_TEST(PCB_FLAG_VISIT, pin)) { + pcb_clear_flag_on_lines_polys(pcb_true, PCB_FLAG_FOUND); + pcb_clear_flag_on_pins_vias_pads(pcb_true, PCB_FLAG_FOUND); + pcb_lookup_conn_by_pin(PCB_TYPE_PIN, pin); + sprintf(nodename, "%s-%s", element->Name[1].TextString, pin->Number); + netname = pcb_netnode_to_netname(nodename); +/* pcb_message(PCB_MSG_INFO, "Netname: %s\n", netname->Name +2); */ + if (netname) { + strcpy(net, &netname->Name[2]); + CheckNetLength(net, aliaslist); + } + else { + strcpy(net, "N/C"); + } + IPCD356_WriteNet(fp, net); + } + PCB_END_LOOP; /* Pin. */ + PCB_PAD_LOOP(element); + if (!PCB_FLAG_TEST(PCB_FLAG_VISIT, pad)) { + pcb_clear_flag_on_lines_polys(pcb_true, PCB_FLAG_FOUND); + pcb_clear_flag_on_pins_vias_pads(pcb_true, PCB_FLAG_FOUND); + pcb_lookup_conn_by_pin(PCB_TYPE_PAD, pad); + sprintf(nodename, "%s-%s", element->Name[1].TextString, pad->Number); + netname = pcb_netnode_to_netname(nodename); +/* pcb_message(PCB_MSG_INFO, "Netname: %s\n", netname->Name +2); */ + if (netname) { + strcpy(net, &netname->Name[2]); + CheckNetLength(net, aliaslist); + } + else { + strcpy(net, "N/C"); + } + IPCD356_WriteNet(fp, net); + } + PCB_END_LOOP; /* Pad. */ + + PCB_END_LOOP; /* Element. */ + + PCB_VIA_LOOP(PCB->Data); + if (!PCB_FLAG_TEST(PCB_FLAG_VISIT, via)) { + pcb_clear_flag_on_lines_polys(pcb_true, PCB_FLAG_FOUND); + pcb_clear_flag_on_pins_vias_pads(pcb_true, PCB_FLAG_FOUND); + pcb_lookup_conn_by_pin(PCB_TYPE_PIN, via); + strcpy(net, "N/C"); + IPCD356_WriteNet(fp, net); + } + PCB_END_LOOP; /* Via. */ + + IPCD356_End(fp); + fclose(fp); + free(aliaslist); + ResetVisitPinsViasAndPads(); + pcb_clear_flag_on_lines_polys(pcb_true, PCB_FLAG_FOUND); + pcb_clear_flag_on_pins_vias_pads(pcb_true, PCB_FLAG_FOUND); + return 0; +} + +void IPCD356_End(FILE * fd) +{ + fprintf(fd, "999\n"); +} + +void ResetVisitPinsViasAndPads() +{ + PCB_VIA_LOOP(PCB->Data); + PCB_FLAG_CLEAR(PCB_FLAG_VISIT, via); + PCB_END_LOOP; /* Via. */ + PCB_ELEMENT_LOOP(PCB->Data); + PCB_PIN_LOOP(element); + PCB_FLAG_CLEAR(PCB_FLAG_VISIT, pin); + PCB_END_LOOP; /* Pin. */ + PCB_PAD_LOOP(element); + PCB_FLAG_CLEAR(PCB_FLAG_VISIT, pad); + PCB_END_LOOP; /* Pad. */ + PCB_END_LOOP; /* Element. */ +} + +int IPCD356_WriteAliases(FILE * fd, IPCD356_AliasList * aliaslist) +{ + int index; + int i; + + index = 1; + + for (i = 0; i < PCB->NetlistLib[PCB_NETLIST_EDITED].MenuN; i++) { + if (strlen(PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i].Name + 2) > 14) { + if (index == 1) { + fprintf(fd, "C Netname Aliases Section\n"); + } + aliaslist = AddAliasToList(aliaslist); + if (aliaslist == NULL) { + return 1; + } + sprintf(aliaslist->Alias[index].NName, "NNAME%-5.5d", index); + strcpy(aliaslist->Alias[index].NetName, PCB->NetlistLib[PCB_NETLIST_EDITED].Menu[i].Name + 2); + + fprintf(fd, "P %s %-58.58s\n", aliaslist->Alias[index].NName, aliaslist->Alias[index].NetName); + index++; + } + } + if (index > 1) { + fprintf(fd, "C End Netname Aliases Section\nC \n"); + } + return 0; +} + +IPCD356_AliasList *CreateAliasList() +{ + IPCD356_AliasList *aliaslist; + + aliaslist = malloc(sizeof(IPCD356_AliasList)); /* Create an alias list. */ + aliaslist->AliasN = 0; /* Initialize Number of Alias. */ + return aliaslist; +} + +IPCD356_AliasList *AddAliasToList(IPCD356_AliasList * aliaslist) +{ + aliaslist->AliasN++; + aliaslist->Alias = realloc(aliaslist->Alias, sizeof(IPCD356_Alias) * (aliaslist->AliasN + 1)); + if (aliaslist->Alias == NULL) { + return NULL; + } + return aliaslist; +} + +void CheckNetLength(char *net, IPCD356_AliasList * aliaslist) +{ + int i; + + if (strlen(net) > 14) { + for (i = 1; i <= aliaslist->AliasN; i++) { + if (strcmp(net, aliaslist->Alias[i].NetName) == 0) { + strcpy(net, aliaslist->Alias[i].NName); + } + } + } +} + +int IPCD356_SanityCheck() +{ + PCB_ELEMENT_LOOP(PCB->Data); + if (element->Name[1].TextString == '\0') { + pcb_message(PCB_MSG_ERROR, "Error: Found unnamed element. All elements need to be named to create an IPC-D-356 netlist.\n"); + return (1); + } + PCB_END_LOOP; /* Element. */ + return (0); +} + +static void IPCD356_do_export(pcb_hid_attr_val_t * options) +{ + int i; + + if (!options) { + IPCD356_get_export_options(0); + + for (i = 0; i < NUM_OPTIONS; i++) + IPCD356_values[i] = IPCD356_options[i].default_val; + + options = IPCD356_values; + } + + IPCD356_filename = options[HA_IPCD356_filename].str_value; + if (!IPCD356_filename) + IPCD356_filename = "pcb-out.net"; + + IPCD356_Netlist(); +} + +static void IPCD356_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_parse_command_line(argc, argv); +} + +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) +{ + 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 a 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/1.2.7/src_plugins/export_lpr/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_lpr/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_lpr/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_lpr + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_lpr/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_lpr/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_lpr/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_lpr/export_lpr.pup =================================================================== --- tags/1.2.7/src_plugins/export_lpr/export_lpr.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_lpr/export_lpr.pup (revision 13657) @@ -0,0 +1,9 @@ +$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 +default buildin +dep export_ps +autoload 1 Index: tags/1.2.7/src_plugins/export_lpr/lpr.c =================================================================== --- tags/1.2.7/src_plugins/export_lpr/lpr.c (nonexistent) +++ tags/1.2.7/src_plugins/export_lpr/lpr.c (revision 13657) @@ -0,0 +1,147 @@ +#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 "hid_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 void lpr_parse_arguments(int *argc, char ***argv) +{ + lpr_get_export_options(0); + pcb_hid_register_attributes(lpr_options, num_lpr_options, lpr_cookie, 0); + 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_hid_remove_actions_by_cookie(lpr_cookie); +} + +int pplg_init_export_lpr(void) +{ + 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/1.2.7/src_plugins/export_nelma/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_nelma/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_nelma/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_nelma + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_nelma/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_nelma/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_nelma/Plug.tmpasm (revision 13657) @@ -0,0 +1,16 @@ +put /local/pcb/mod {export_nelma} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_nelma/nelma.o @] + +switch /local/pcb/export_nelma/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_nelma/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/1.2.7/src_plugins/export_nelma/export_nelma.pup =================================================================== --- tags/1.2.7/src_plugins/export_nelma/export_nelma.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_nelma/export_nelma.pup (revision 13657) @@ -0,0 +1,8 @@ +$class export +$short nelma pcb_exporter +$long Export to nelma (Numerical capacitance calculator) +$state works +$fmt-native no +$fmt-feature-w export a board in the nelma format for Numerical capacitance calculation +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_nelma/nelma.c =================================================================== --- tags/1.2.7/src_plugins/export_nelma/nelma.c (nonexistent) +++ tags/1.2.7/src_plugins/export_nelma/nelma.c (revision 13657) @@ -0,0 +1,1013 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * NELMA (Numerical capacitance calculator) export HID + * Copyright (C) 2006 Tomaz Solc (tomaz.solc@tablix.org) + * + * PNG export code is based on the PNG export HID + * 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. + * + */ + +/* + * This HID exports a PCB layout into: o One layer mask file (PNG format) per + * copper layer. o Nelma configuration file that contains netlist and pin + * information. + */ + +/* + * FIXME: + * + * If you have a section of a net that does not contain any pins then that + * section will be missing from the Nelma's copper geometry. + * + * For example: + * + * this section will be ignored by Nelma | | + * + * || ||=======|| || component layer || + * || || || ||=============|| ||============|| + * solder layer + * + * pin1 via via pin2 + * + * Single layer layouts are always exported correctly. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include + +#include "board.h" +#include "error.h" +#include "data.h" +#include "layer.h" +#include "rats.h" +#include "plugins.h" +#include "hid_helper.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include + +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_flags.h" +#include "hid_color.h" + +const char *nelma_cookie = "nelma HID"; + +#define CRASH(func) fprintf(stderr, "HID error: pcb called unimplemented PNG function %s.\n", func); abort() + +/* Needed for PNG export */ + +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_hid_t *me_pointer; + pcb_cap_style_t cap; + pcb_coord_t width; + unsigned char r, g, b; + int erase; + int faded; + struct color_struct *color; + gdImagePtr brush; +}; + +static pcb_hid_t nelma_hid; + +static struct color_struct *black = NULL, *white = NULL; +static pcb_coord_t linewidth = -1; +static gdImagePtr lastbrush = (gdImagePtr) ((void *) -1); +static int lastcolor = -1; + +/* gd image and file for PNG export */ +static gdImagePtr nelma_im = NULL; +static FILE *nelma_f = NULL; + +static int is_mask; +static int is_drill; + +/* + * Which groups of layers to export into PNG layer masks. 1 means export, 0 + * means do not export. + */ +static int nelma_export_group[PCB_MAX_LAYERGRP]; + +/* Group that is currently exported. */ +static int nelma_cur_group; + +/* Filename prefix that will be used when saving files. */ +static const char *nelma_basename = NULL; + +/* Horizontal DPI (grid points per inch) */ +static int nelma_dpi = -1; + +/* Height of the copper layers in micrometers. */ + +/* + * The height of the copper layer is currently taken as the vertical grid + * step, since this is the smallest vertical feature in the layout. + */ +static int nelma_copperh = -1; +/* Height of the substrate layers in micrometers. */ +static int nelma_substrateh = -1; +/* Relative permittivity of the substrate. */ +static double nelma_substratee = -1; + +/* Permittivity of empty space (As/Vm) */ +static const double nelma_air_epsilon = 8.85e-12; + +pcb_hid_attribute_t nelma_attribute_list[] = { + /* other HIDs expect this to be first. */ + +/* %start-doc options "nelma Options" +@ftable @code +@item -- basename +File name prefix. +@end ftable +%end-doc +*/ + {"basename", "File name prefix", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_basename 0 + +/* %start-doc options "nelma Options" +@ftable @code +@item --dpi +Horizontal scale factor (grid points/inch). +@end ftable +%end-doc +*/ + {"dpi", "Horizontal scale factor (grid points/inch)", + PCB_HATT_INTEGER, 0, 1000, {100, 0, 0}, 0, 0}, +#define HA_dpi 1 + +/* %start-doc options "nelma Options" +@ftable @code +@item --copper-height +Copper layer height (um). +@end ftable +%end-doc +*/ + {"copper-height", "Copper layer height (um)", + PCB_HATT_INTEGER, 0, 200, {100, 0, 0}, 0, 0}, +#define HA_copperh 2 + +/* %start-doc options "nelma Options" +@ftable @code +@item --substrate-height +Substrate layer height (um). +@end ftable +%end-doc +*/ + {"substrate-height", "Substrate layer height (um)", + PCB_HATT_INTEGER, 0, 10000, {2000, 0, 0}, 0, 0}, +#define HA_substrateh 3 + +/* %start-doc options "nelma Options" +@ftable @code +@item --substrate-epsilon +Substrate relative epsilon. +@end ftable +%end-doc +*/ + {"substrate-epsilon", "Substrate relative epsilon", + PCB_HATT_REAL, 0, 100, {0, 0, 4.0}, 0, 0}, +#define HA_substratee 4 +}; + +#define NUM_OPTIONS (sizeof(nelma_attribute_list)/sizeof(nelma_attribute_list[0])) + +PCB_REGISTER_ATTRIBUTES(nelma_attribute_list, nelma_cookie) + static pcb_hid_attr_val_t nelma_values[NUM_OPTIONS]; + +/* *** Utility funcions **************************************************** */ + +/* convert from default PCB units to nelma units */ + static int pcb_to_nelma(pcb_coord_t pcb) +{ + return PCB_COORD_TO_INCH(pcb) * nelma_dpi; +} + +static char *nelma_get_png_name(const char *basename, const char *suffix) +{ + char *buf; + int len; + + len = strlen(basename) + strlen(suffix) + 6; + buf = (char *) malloc(sizeof(*buf) * len); + + sprintf(buf, "%s.%s.png", basename, suffix); + + return buf; +} + +/* *** Exporting netlist data and geometry to the nelma config file ******** */ + +static void nelma_write_space(FILE * out) +{ + double xh, zh; + int z, i; + + xh = 2.54e-2 / ((double) nelma_dpi); + zh = nelma_copperh * 1e-6; + + fprintf(out, "\n/* **** Space **** */\n\n"); + + fprintf(out, "space pcb {\n"); + fprintf(out, "\tstep = { %e, %e, %e }\n", xh, xh, zh); + fprintf(out, "\tlayers = {\n"); + + fprintf(out, "\t\t\"air-top\",\n"); + fprintf(out, "\t\t\"air-bottom\""); + + z = 10; + for (i = 0; i < PCB_MAX_LAYERGRP; i++) + if (nelma_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *ext = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB_FNS_fixed); + + if (z != 10) { + fprintf(out, ",\n"); + fprintf(out, "\t\t\"substrate-%d\"", z); + z++; + } + fprintf(out, ",\n"); + fprintf(out, "\t\t\"%s\"", ext); + z++; + } + fprintf(out, "\n\t}\n"); + fprintf(out, "}\n"); +} + + +static void nelma_write_material(FILE * out, const char *name, const char *type, double e) +{ + fprintf(out, "material %s {\n", name); + fprintf(out, "\ttype = \"%s\"\n", type); + fprintf(out, "\tpermittivity = %e\n", e); + fprintf(out, "\tconductivity = 0.0\n"); + fprintf(out, "\tpermeability = 0.0\n"); + fprintf(out, "}\n"); +} + +static void nelma_write_materials(FILE * out) +{ + fprintf(out, "\n/* **** Materials **** */\n\n"); + + nelma_write_material(out, "copper", "metal", nelma_air_epsilon); + nelma_write_material(out, "air", "dielectric", nelma_air_epsilon); + nelma_write_material(out, "composite", "dielectric", nelma_air_epsilon * nelma_substratee); +} + +static void nelma_write_nets(FILE * out) +{ + pcb_lib_t netlist; + pcb_lib_menu_t *net; + pcb_lib_entry_t *pin; + + int n, m, i; + + netlist = PCB->NetlistLib[PCB_NETLIST_EDITED]; + + fprintf(out, "\n/* **** Nets **** */\n\n"); + + for (n = 0; n < netlist.MenuN; n++) { + net = &netlist.Menu[n]; + + /* Weird, but correct */ + fprintf(out, "net %s {\n", &net->Name[2]); + + fprintf(out, "\tobjects = {\n"); + + for (m = 0; m < net->EntryN; m++) { + pin = &net->Entry[m]; + + /* pcb_pin_name_to_xy(pin, &x, &y); */ + + for (i = 0; i < PCB_MAX_LAYERGRP; i++) + if (nelma_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *ext = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB_FNS_fixed); + + if (m != 0 || i != 0) + fprintf(out, ",\n"); + fprintf(out, "\t\t\"%s-%s\"", pin->ListEntry, ext); + } + } + + fprintf(out, "\n"); + fprintf(out, "\t}\n"); + fprintf(out, "}\n"); + } +} + +static void nelma_write_layer(FILE * out, int z, int h, const char *name, int full, const char *mat) +{ + pcb_lib_t netlist; + pcb_lib_menu_t *net; + pcb_lib_entry_t *pin; + + int n, m; + + fprintf(out, "layer %s {\n", name); + fprintf(out, "\theight = %d\n", h); + fprintf(out, "\tz-order = %d\n", z); + fprintf(out, "\tmaterial = \"%s\"\n", mat); + + if (full) { + fprintf(out, "\tobjects = {\n"); + netlist = PCB->NetlistLib[PCB_NETLIST_EDITED]; + + for (n = 0; n < netlist.MenuN; n++) { + net = &netlist.Menu[n]; + + for (m = 0; m < net->EntryN; m++) { + pin = &net->Entry[m]; + + if (m != 0 || n != 0) + fprintf(out, ",\n"); + fprintf(out, "\t\t\"%s-%s\"", pin->ListEntry, name); + } + + } + fprintf(out, "\n\t}\n"); + } + fprintf(out, "}\n"); +} + +static void nelma_write_layers(FILE * out) +{ + int i, subh, z; + char buf[100]; + + subh = nelma_substrateh / nelma_copperh; + + fprintf(out, "\n/* **** Layers **** */\n\n"); + + /* Air layers on top and bottom of the stack */ + /* Their height is double substrate height. */ + nelma_write_layer(out, 1, 2 * subh, "air-top", 0, "air"); + nelma_write_layer(out, 1000, 2 * subh, "air-bottom", 0, "air"); + + z = 10; + for (i = 0; i < PCB_MAX_LAYERGRP; i++) + if (nelma_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *ext = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB_FNS_fixed); + + if (z != 10) { + sprintf(buf, "substrate-%d", z); + nelma_write_layer(out, z, subh, buf, 0, "composite"); + z++; + } + /* + * FIXME: for layers that are not on top or bottom, + * the material should be "composite" + */ + nelma_write_layer(out, z, 1, ext, 1, "air"); + + z++; + } +} + +static void nelma_write_object(FILE * out, pcb_lib_entry_t *pin) +{ + pcb_coord_t px = 0, py = 0; + int x, y, i; + char *f; + + pcb_pin_name_to_xy(pin, &px, &py); + + x = pcb_to_nelma(px); + y = pcb_to_nelma(py); + + for (i = 0; i < PCB_MAX_LAYERGRP; i++) + if (nelma_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *ext = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB_FNS_fixed); + + fprintf(out, "object %s-%s {\n", pin->ListEntry, ext); + fprintf(out, "\tposition = { 0, 0 }\n"); + fprintf(out, "\tmaterial = \"copper\"\n"); + fprintf(out, "\ttype = \"image\"\n"); + fprintf(out, "\trole = \"net\"\n"); + + f = nelma_get_png_name(nelma_basename, ext); + + fprintf(out, "\tfile = \"%s\"\n", f); + + free(f); + + fprintf(out, "\tfile-pos = { %d, %d }\n", x, y); + fprintf(out, "}\n"); + } +} + +static void nelma_write_objects(FILE * out) +{ + pcb_lib_t netlist; + pcb_lib_menu_t *net; + pcb_lib_entry_t *pin; + + int n, m; + + netlist = PCB->NetlistLib[PCB_NETLIST_EDITED]; + + fprintf(out, "\n/* **** Objects **** */\n\n"); + + for (n = 0; n < netlist.MenuN; n++) { + net = &netlist.Menu[n]; + + for (m = 0; m < net->EntryN; m++) { + pin = &net->Entry[m]; + + nelma_write_object(out, pin); + } + } +} + +/* *** Main export callback ************************************************ */ + +static void nelma_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(nelma_attribute_list, sizeof(nelma_attribute_list) / sizeof(nelma_attribute_list[0]), nelma_cookie, 0); + pcb_hid_parse_command_line(argc, argv); +} + +static pcb_hid_attribute_t *nelma_get_export_options(int *n) +{ + static char *last_made_filename = 0; + + if (PCB) { + pcb_derive_default_filename(PCB->Filename, &nelma_attribute_list[HA_basename], ".nelma", &last_made_filename); + } + if (n) { + *n = NUM_OPTIONS; + } + return nelma_attribute_list; +} + +/* Populates nelma_export_group array */ +void nelma_choose_groups() +{ + int n, m; + pcb_layer_t *layer; + + /* Set entire array to 0 (don't export any layer groups by default */ + memset(nelma_export_group, 0, sizeof(nelma_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 */ + if ((flags & PCB_LYT_COPPER) || (flags & PCB_LYT_OUTLINE)) { + /* layer is a copper layer */ + m = pcb_layer_get_group(PCB, n); + + /* the export layer */ + nelma_export_group[m] = 1; + } + } + } +} + +static void nelma_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(nelma_im, white->r, white->g, white->b); + + black = (struct color_struct *) malloc(sizeof(*black)); + black->r = black->g = black->b = 0; + black->c = gdImageColorAllocate(nelma_im, black->r, black->g, black->b); +} + +static void nelma_start_png(const char *basename, const char *suffix) +{ + int h, w; + char *buf; + + buf = nelma_get_png_name(basename, suffix); + + h = pcb_to_nelma(PCB->MaxHeight); + w = pcb_to_nelma(PCB->MaxWidth); + + /* nelma_im = gdImageCreate (w, h); */ + + /* Nelma only works with true color images */ + nelma_im = gdImageCreate(w, h); + nelma_f = pcb_fopen(buf, "wb"); + + nelma_alloc_colors(); + + free(buf); +} + +static void nelma_finish_png() +{ +#ifdef HAVE_GDIMAGEPNG + gdImagePng(nelma_im, nelma_f); +#else + pcb_message(PCB_MSG_WARNING, "NELMA: PNG not supported by gd. Can't write layer mask.\n"); +#endif + gdImageDestroy(nelma_im); + fclose(nelma_f); + + free(white); + free(black); + + nelma_im = NULL; + nelma_f = NULL; +} + +void nelma_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(&nelma_hid, &ctx); +} + +static void nelma_do_export(pcb_hid_attr_val_t * options) +{ + int save_ons[PCB_MAX_LAYER + 2]; + int i, len; + FILE *nelma_config; + char *buf; + time_t t; + + if (!options) { + nelma_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) { + nelma_values[i] = nelma_attribute_list[i].default_val; + } + options = nelma_values; + } + nelma_basename = options[HA_basename].str_value; + if (!nelma_basename) { + nelma_basename = "pcb-out"; + } + nelma_dpi = options[HA_dpi].int_value; + if (nelma_dpi < 0) { + fprintf(stderr, "ERROR: dpi may not be < 0\n"); + return; + } + nelma_copperh = options[HA_copperh].int_value; + nelma_substrateh = options[HA_substrateh].int_value; + nelma_substratee = options[HA_substratee].real_value; + + nelma_choose_groups(); + + for (i = 0; i < PCB_MAX_LAYERGRP; i++) { + if (nelma_export_group[i]) { + char tmp_ln[PCB_PATH_MAX]; + const char *ext = pcb_layer_to_file_name(tmp_ln, -1, pcb_layergrp_flags(PCB, i), PCB_FNS_fixed); + + nelma_cur_group = i; + + nelma_start_png(nelma_basename, ext); + + pcb_hid_save_and_show_layer_ons(save_ons); + nelma_start_png_export(); + pcb_hid_restore_layer_ons(save_ons); + + nelma_finish_png(); + } + } + + len = strlen(nelma_basename) + 4; + buf = (char *) malloc(sizeof(*buf) * len); + + sprintf(buf, "%s.em", nelma_basename); + nelma_config = pcb_fopen(buf, "w"); + + free(buf); + + fprintf(nelma_config, "/* Made with PCB Nelma export HID */"); + t = time(NULL); + fprintf(nelma_config, "/* %s */", ctime(&t)); + + nelma_write_nets(nelma_config); + nelma_write_objects(nelma_config); + nelma_write_layers(nelma_config); + nelma_write_materials(nelma_config); + nelma_write_space(nelma_config); + + fclose(nelma_config); +} + +/* *** PNG export (slightly modified code from PNG export HID) ************* */ + +static int nelma_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + if (flags & PCB_LYT_INVIS) + return 0; + + if ((flags & PCB_LYT_ANYTHING) == PCB_LYT_SILK) + return 0; + + is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + 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 == nelma_cur_group) { + return 1; + } + return 0; +} + +static pcb_hid_gc_t nelma_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) malloc(sizeof(struct hid_gc_s)); + rv->me_pointer = &nelma_hid; + rv->cap = Trace_Cap; + 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 nelma_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void nelma_set_color(pcb_hid_gc_t gc, const char *name) +{ + if (nelma_im == NULL) { + return; + } + if (name == NULL) { + name = "#ff0000"; + } + if (!strcmp(name, "drill")) { + gc->color = black; + gc->erase = 0; + return; + } + if (!strcmp(name, "erase")) { + /* FIXME -- should be background, not white */ + gc->color = white; + gc->erase = 1; + return; + } + gc->color = black; + gc->erase = 0; + return; +} + +static void nelma_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void nelma_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void nelma_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + +static void nelma_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 != &nelma_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to nelma 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(nelma_im, pcb_to_nelma(gc->width)); + 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 Round_Cap: + case Trace_Cap: + type = 'C'; + r = pcb_to_nelma(gc->width / 2); + break; + default: + case Square_Cap: + r = pcb_to_nelma(gc->width); + type = 'S'; + break; + } + 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(nelma_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 nelma_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(nelma_im, pcb_to_nelma(x1), pcb_to_nelma(y1), pcb_to_nelma(x2), pcb_to_nelma(y2), gc->color->c); +} + +static void nelma_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(nelma_im, 0); + linewidth = 0; + gdImageFilledRectangle(nelma_im, pcb_to_nelma(x1), pcb_to_nelma(y1), pcb_to_nelma(x2), pcb_to_nelma(y2), gc->color->c); +} + +static void nelma_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; + nelma_fill_rect(gc, x1 - w, y1 - w, x1 + w, y1 + w); + return; + } + use_gc(gc); + + gdImageSetThickness(nelma_im, 0); + linewidth = 0; + gdImageLine(nelma_im, pcb_to_nelma(x1), pcb_to_nelma(y1), pcb_to_nelma(x2), pcb_to_nelma(y2), gdBrushed); +} + +static void nelma_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(nelma_im, 0); + linewidth = 0; + gdImageArc(nelma_im, pcb_to_nelma(cx), pcb_to_nelma(cy), + pcb_to_nelma(2 * width), pcb_to_nelma(2 * height), sa, ea, gdBrushed); +} + +static void nelma_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + use_gc(gc); + + gdImageSetThickness(nelma_im, 0); + linewidth = 0; + gdImageFilledEllipse(nelma_im, pcb_to_nelma(cx), pcb_to_nelma(cy), + pcb_to_nelma(2 * radius), pcb_to_nelma(2 * radius), gc->color->c); + +} + +static void nelma_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: nelma_fill_polygon(): malloc failed\n"); + exit(1); + } + use_gc(gc); + for (i = 0; i < n_coords; i++) { + points[i].x = pcb_to_nelma(x[i]+dx); + points[i].y = pcb_to_nelma(y[i]+dy); + } + gdImageSetThickness(nelma_im, 0); + linewidth = 0; + gdImageFilledPolygon(nelma_im, points, n_coords, gc->color->c); + free(points); +} + +static void nelma_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + nelma_fill_polygon_offs(gc, n_coords, x, y, 0, 0); +} + + +static void nelma_calibrate(double xval, double yval) +{ + CRASH("nelma_calibrate"); +} + +static void nelma_set_crosshair(int x, int y, int a) +{ +} + +static int nelma_usage(const char *topic) +{ + fprintf(stderr, "\nnelma exporter command line arguments:\n\n"); + pcb_hid_usage(nelma_attribute_list, sizeof(nelma_attribute_list) / sizeof(nelma_attribute_list[0])); + fprintf(stderr, "\nUsage: pcb-rnd [generic_options] -x nelma [nelma options] foo.pcb\n\n"); + return 0; +} + +/* *** Miscellaneous ******************************************************* */ + +#include "dolists.h" + +int pplg_check_ver_export_nelma(int ver_needed) { return 0; } + +int pplg_uninit_export_nelma(void) +{ + pcb_hid_remove_attributes_by_cookie(nelma_cookie); + return 0; +} + +int pplg_init_export_nelma(void) +{ + memset(&nelma_hid, 0, sizeof(pcb_hid_t)); + + pcb_hid_nogui_init(&nelma_hid); + pcb_dhlp_draw_helpers_init(&nelma_hid); + + nelma_hid.struct_size = sizeof(pcb_hid_t); + nelma_hid.name = "nelma"; + nelma_hid.description = "Numerical analysis package export"; + nelma_hid.exporter = 1; + + nelma_hid.get_export_options = nelma_get_export_options; + nelma_hid.do_export = nelma_do_export; + nelma_hid.parse_arguments = nelma_parse_arguments; + nelma_hid.set_layer_group = nelma_set_layer_group; + nelma_hid.make_gc = nelma_make_gc; + nelma_hid.destroy_gc = nelma_destroy_gc; + nelma_hid.set_color = nelma_set_color; + nelma_hid.set_line_cap = nelma_set_line_cap; + nelma_hid.set_line_width = nelma_set_line_width; + nelma_hid.set_draw_xor = nelma_set_draw_xor; + nelma_hid.set_draw_faded = nelma_set_draw_faded; + nelma_hid.draw_line = nelma_draw_line; + nelma_hid.draw_arc = nelma_draw_arc; + nelma_hid.draw_rect = nelma_draw_rect; + nelma_hid.fill_circle = nelma_fill_circle; + nelma_hid.fill_polygon = nelma_fill_polygon; + nelma_hid.fill_polygon_offs = nelma_fill_polygon_offs; + nelma_hid.fill_rect = nelma_fill_rect; + nelma_hid.calibrate = nelma_calibrate; + nelma_hid.set_crosshair = nelma_set_crosshair; + + nelma_hid.usage = nelma_usage; + + pcb_hid_register_hid(&nelma_hid); + return 0; +} Index: tags/1.2.7/src_plugins/export_openscad/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_openscad/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_openscad + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_openscad/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_openscad/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_openscad/export_openscad.c =================================================================== --- tags/1.2.7/src_plugins/export_openscad/export_openscad.c (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/export_openscad.c (revision 13657) @@ -0,0 +1,698 @@ + /* + * 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. + * + */ + +#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 "error.h" +#include "layer.h" +#include "math_helper.h" +#include "misc_util.h" +#include "plugins.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" + +#include "hid_init.h" +#include "hid_actions.h" +#include "hid_attrib.h" +#include "hid_color.h" +#include "hid_helper.h" +#include "hid_flags.h" + + +static pcb_hid_t openscad_hid; + +const char *openscad_cookie = "openscad HID"; + + +typedef struct hid_gc_s { + 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) +{ + static char *last_made_filename = 0; + const char *suffix = ".scad"; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &openscad_attribute_list[HA_openscadfile], suffix, &last_made_filename); + + 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); + + 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 void 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); + pcb_hid_parse_command_line(argc, argv); +} + + + +static int openscad_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_INVIS) + return 0; + + if (flags & PCB_LYT_OUTLINE) { + return 0; + } + + if (flags & PCB_LYT_PDRILL) + return 0; + + if (flags & PCB_LYT_UDRILL) + 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: + 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 char *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 == Square_Cap) + 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(int x, int 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 int pcb_act_scad_export_poly(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + FILE *f; + + if (argc <= 0) { + pcb_message(PCB_MSG_ERROR, "Need a file name to export to.\n"); + return -1; + } + f = pcb_fopen(argv[0], "w"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to open %s for writing\n", argv[0]); + return -1; + } + + + 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); + return 0; +} + + +static pcb_hid_action_t scad_action_list[] = { + {"ExportScadPoly", 0, 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_hid_remove_actions_by_cookie(openscad_cookie); +} + +int pplg_init_export_openscad(void) +{ + 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.holes_after = 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/1.2.7/src_plugins/export_openscad/export_openscad.pup =================================================================== --- tags/1.2.7/src_plugins/export_openscad/export_openscad.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/export_openscad.pup (revision 13657) @@ -0,0 +1,9 @@ +$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 +dep lib_polyhelp +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_openscad/scad_draw.c =================================================================== --- tags/1.2.7/src_plugins/export_openscad/scad_draw.c (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/scad_draw.c (revision 13657) @@ -0,0 +1,160 @@ + /* + * 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. + * + */ + +#include "../lib_polyhelp/topoly.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_drill(const pcb_pin_t *pin) +{ + pcb_fprintf(f, " translate([%mm,%mm,0])\n", TRX_(pin->X), TRY_(pin->Y)); + pcb_fprintf(f, " cylinder(r=%mm, h=4, center=true, $fn=30);\n", pin->DrillingHole/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->via_tree, &it); obj != NULL; obj = pcb_r_next(&it)) + scad_draw_drill((pcb_pin_t *)obj); + pcb_r_end(&it); + + PCB_PIN_ALL_LOOP(PCB->Data); { + scad_draw_drill(pin); + } PCB_ENDALL_LOOP; + + + 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/1.2.7/src_plugins/export_openscad/scad_models.c =================================================================== --- tags/1.2.7/src_plugins/export_openscad/scad_models.c (nonexistent) +++ tags/1.2.7/src_plugins/export_openscad/scad_models.c (revision 13657) @@ -0,0 +1,106 @@ + /* + * 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. + * + */ + +#include "conf_core.h" + +static void scad_insert_model(htsp_t *models, const char *name, pcb_coord_t x0, pcb_coord_t y0, 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) { + const char *tab = ""; + pcb_append_printf(&model_calls, " translate([%mm,%mm,0.8])\n", x0, y0); + if (transf != NULL) { + pcb_append_printf(&model_calls, " %s\n", transf); + tab = "\t"; + } + 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_ELEMENT_LOOP(PCB->Data); { + mod = pcb_attribute_get(&element->Attributes, "openscad"); + if (mod != NULL) { + transf = pcb_attribute_get(&element->Attributes, "openscad-transformation"); + param = pcb_attribute_get(&element->Attributes, "openscad-param"); + scad_insert_model(&models, mod, TRX_(element->MarkX), TRY_(element->MarkY), transf, param); + } + } PCB_END_LOOP; + + for (e = htsp_first(&models); e; e = htsp_next(&models, e)) + free(e->value); + + htsp_uninit(&models); +} Index: tags/1.2.7/src_plugins/export_png/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_png/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_png/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_png + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_png/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_png/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_png/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_png/export_png.pup =================================================================== --- tags/1.2.7/src_plugins/export_png/export_png.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_png/export_png.pup (revision 13657) @@ -0,0 +1,10 @@ +$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 +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_png/png.c =================================================================== --- tags/1.2.7/src_plugins/export_png/png.c (nonexistent) +++ tags/1.2.7/src_plugins/export_png/png.c (revision 13657) @@ -0,0 +1,1886 @@ + /* + * COPYRIGHT + * + * 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. + * + */ + +/* + * 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 "error.h" +#include "layer.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "plugins.h" +#include "safe_fs.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_helper.h" +#include "hid_flags.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 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_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. +@end ftable +%end-doc +*/ + {"png-bloat", "Amount (in/mm/mil/pix) to add to trace/pad/pin edges (1 = 1/100 mil)", + 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 + + {"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) +{ + static char *last_made_filename = 0; + const char *suffix = get_file_suffix(); + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &png_attribute_list[HA_pngfile], suffix, &last_made_filename); + + 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 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); +} + +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; + + 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; + } + } + } + } + linewidth = -1; + lastbrush = (gdImagePtr) ((void *) -1); + lastcap = -1; + lastgroup = -1; + show_solder_side = conf_core.editor.show_solder_side; + last_color_r = last_color_g = last_color_b = last_cap = -1; + + in_mono = options[HA_mono].int_value; + + 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); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + conf_update(NULL, -1); /* restore forced sets */ +} + +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 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 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; + const char *fmt; + pcb_bool format_error = pcb_false; + + 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; + } + + 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; + } + + 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; + } + + gdImageFilledRectangle(im, 0, 0, gdImageSX(im), gdImageSY(im), white->c); + + 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; + } + + f = pcb_fopen(filename, "wb"); + if (!f) { + perror(filename); + return; + } + + png_hid.force_compositing = !!photo_mode; + + if (!options[HA_as_shown].int_value) + pcb_hid_save_and_show_layer_ons(save_ons); + + png_hid_export_to_file(f, options); + + if (!options[HA_as_shown].int_value) + pcb_hid_restore_layer_ons(save_ons); + + 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]]); + ts_bs(photo_silk); + 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 (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 (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 (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 (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[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[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 (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[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"); + + 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); +} + +static void 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); + pcb_hid_parse_command_line(argc, argv); +} + + +static int is_mask; +static int is_drill; + + +static int png_set_layer_group_photo(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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 ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)) { + photo_im = &photo_drill; + } + else { + if (flags & PCB_LYT_OUTLINE) { + 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 ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)) + 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + doing_outline = 0; + + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if ((flags & PCB_LYT_ASSY) || (flags & PCB_LYT_FAB) || (flags & PCB_LYT_PASTE) || (flags & PCB_LYT_INVIS) || (flags & PCB_LYT_CSECT)) + return 0; + + is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + is_mask = (flags & PCB_LYT_MASK); + + if (photo_mode) + return png_set_layer_group_photo(group, layer, flags, is_empty); + + 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 = Trace_Cap; + 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) + 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: + 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 char *name) +{ + pcb_hidval_t cval; + + if (im == NULL) + return; + + if (name == NULL) + name = "#ff0000"; + + if (strcmp(name, "drill") == 0) { + gc->color = white; + gc->is_erase = 1; + return; + } + gc->is_erase = 0; + + if (in_mono || (strcmp(name, "#000000") == 0)) { + gc->color = black; + return; + } + + if (pcb_hid_cache_color(0, name, &cval, &color_cache)) { + gc->color = (color_struct *) cval.ptr; + } + else if (name[0] == '#') { + gc->color = (color_struct *) malloc(sizeof(color_struct)); + sscanf(name + 1, "%2x%2x%2x", &(gc->color->r), &(gc->color->g), &(gc->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, name, &cval, &color_cache); + } + else if (strcmp(name, "erase") == 0) { + gc->color = black; /* safe to remove */ + } + 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 Round_Cap: + case Trace_Cap: + type = 'C'; + break; + default: + case Square_Cap: + type = 'S'; + break; + } + 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_draw_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); + gdImageRectangle(im, SCALE_X(x1), SCALE_Y(y1), SCALE_X(x2), SCALE_Y(y2), unerase_override ? white->c : gc->color->c); +} + +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_rect_(im, gc, x1, y1, x2, y2); + if ((im != erase_im) && (erase_im != NULL)) { + unerase_override = 1; + png_draw_rect_(erase_im, gc, x1, y1, x2, y2); + unerase_override = 0; + } +} + +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) +{ + if (x1 == x2 && y1 == y2) { + pcb_coord_t w = gc->width / 2; + if (gc->cap != Square_Cap) + 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) { + x1 -= pcb_round(scale / 2); + x2 -= pcb_round(scale / 2); + } + if (y1 == PCB->MaxHeight && y2 == PCB->MaxHeight) { + y1 -= pcb_round(scale / 2); + y2 -= pcb_round(scale / 2); + } + } + + gdImageSetThickness(im, 0); + linewidth = 0; + if (gc->cap != Square_Cap || x1 == x2 || y1 == y2) { + gdImageLine(im, SCALE_X(x1), SCALE_Y(y1), SCALE_X(x2), SCALE_Y(y2), 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_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(int x, int 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) +{ + 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/1.2.7/src_plugins/export_png/png.h =================================================================== --- tags/1.2.7/src_plugins/export_png/png.h (nonexistent) +++ tags/1.2.7/src_plugins/export_png/png.h (revision 13657) @@ -0,0 +1,2 @@ +extern const char *png_cookie; +extern void png_hid_export_to_file(FILE *, pcb_hid_attr_val_t *); Index: tags/1.2.7/src_plugins/export_ps/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_ps/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ps + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_ps/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_ps/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_ps/eps.c =================================================================== --- tags/1.2.7/src_plugins/export_ps/eps.c (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/eps.c (revision 13657) @@ -0,0 +1,664 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "board.h" +#include "data.h" +#include "layer.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_helper.h" +#include "hid_flags.h" +#include "hid_color.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 void eps_parse_arguments(int *argc, char ***argv); +static int eps_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty); +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 char *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_ffs(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(int x, int y, int action); +/*----------------------------------------------------------------------------*/ + +typedef struct hid_gc_s { + 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 +}; + +#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) +{ + static char *last_made_filename = 0; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &eps_attribute_list[HA_psfile], ".eps", &last_made_filename); + + 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; + +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; + + 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); + } + fprintf(f, "%%!PS-Adobe-3.0 EPSF-3.0\n"); + linewidth = -1; + lastcap = -1; + lastcolor = -1; + + in_mono = options[HA_mono].int_value; + +#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", filename); + + 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); + linewidth = -1; + lastcap = -1; + lastcolor = -1; +#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"); + + ctx.view = *bounds; + pcb_hid_expose_all(&eps_hid, &ctx); + + 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"); + + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + conf_update(NULL, -1); /* restore forced sets */ +} + +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; + } + + filename = options[HA_psfile].str_value; + if (!filename) + filename = "pcb-out.eps"; + + f = pcb_fopen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + if (!options[HA_as_shown].int_value) + pcb_hid_save_and_show_layer_ons(save_ons); + eps_hid_export_to_file(f, options); + if (!options[HA_as_shown].int_value) + pcb_hid_restore_layer_ons(save_ons); + + fclose(f); +} + +static void 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); + 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + char tmp_ln[PCB_PATH_MAX]; + const char *name; + + if (flags & PCB_LYT_UI) + return 0; + + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if ((flags & PCB_LYT_ASSY) || (flags & PCB_LYT_FAB) || (flags & PCB_LYT_CSECT) || (flags & PCB_LYT_INVIS)) + return 0; + + if ((group >= 0) && pcb_layergrp_is_empty(PCB, group) && (flags & PCB_LYT_OUTLINE)) + return 0; + + is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + 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, 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 = Trace_Cap; + 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_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 char *name) +{ + static void *cache = 0; + pcb_hidval_t cval; + + if (drawing_mode == PCB_HID_COMP_NEGATIVE) { + gc->color = 0xffffff; + gc->erase = 1; + return; + } + if (strcmp(name, "erase") == 0) { + gc->color = 0xffffff; + gc->erase = fast_erase ? 0 : 1; + return; + } + if (strcmp(name, "drill") == 0) { + gc->color = 0xffffff; + gc->erase = 0; + return; + } + gc->erase = 0; + if (pcb_hid_cache_color(0, name, &cval, &cache)) { + gc->color = cval.lval; + } + else if (in_mono) { + gc->color = 0; + } + else if (name[0] == '#') { + unsigned int r, g, b; + sscanf(name + 1, "%2x%2x%2x", &r, &g, &b); + gc->color = (r << 16) + (g << 8) + 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 Round_Cap: + case Trace_Cap: + c = 1; + break; + default: + case Square_Cap: + c = 2; + break; + } + 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 == Square_Cap) + 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 != Square_Cap) { + 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(int x, int 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/1.2.7/src_plugins/export_ps/export_ps.pup =================================================================== --- tags/1.2.7/src_plugins/export_ps/export_ps.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/export_ps.pup (revision 13657) @@ -0,0 +1,9 @@ +$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) +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_ps/ps.c =================================================================== --- tags/1.2.7/src_plugins/export_ps/ps.c (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/ps.c (revision 13657) @@ -0,0 +1,1662 @@ +#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_helper.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_flags.h" +#include "hid_actions.h" +#include "conf_core.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "stub_draw.h" + +const char *ps_cookie = "ps HID"; + +static int ps_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty); +static void use_gc(pcb_hid_gc_t gc); + +typedef struct hid_gc_s { + 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 const char *medias[] = { + "A0", "A1", "A2", "A3", "A4", "A5", + "A6", "A7", "A8", "A9", "A10", + "B0", "B1", "B2", "B3", "B4", "B5", + "B6", "B7", "B8", "B9", "B10", + "Letter", "11x17", "Ledger", + "Legal", "Executive", + "A-Size", "B-size", + "C-Size", "D-size", "E-size", + "US-Business_Card", "Intl-Business_Card", + 0 +}; + +typedef struct { + const char *name; + pcb_coord_t Width, Height; + pcb_coord_t MarginX, MarginY; +} MediaType, *MediaTypePtr; + +/* + * Metric ISO sizes in mm. See http://en.wikipedia.org/wiki/ISO_paper_sizes + * + * A0 841 x 1189 + * A1 594 x 841 + * A2 420 x 594 + * A3 297 x 420 + * A4 210 x 297 + * A5 148 x 210 + * A6 105 x 148 + * A7 74 x 105 + * A8 52 x 74 + * A9 37 x 52 + * A10 26 x 37 + * + * B0 1000 x 1414 + * B1 707 x 1000 + * B2 500 x 707 + * B3 353 x 500 + * B4 250 x 353 + * B5 176 x 250 + * B6 125 x 176 + * B7 88 x 125 + * B8 62 x 88 + * B9 44 x 62 + * B10 31 x 44 + * + * awk '{printf(" {\"%s\", %d, %d, MARGINX, MARGINY},\n", $2, $3*100000/25.4, $5*100000/25.4)}' + * + * See http://en.wikipedia.org/wiki/Paper_size#Loose_sizes for some of the other sizes. The + * {A,B,C,D,E}-Size here are the ANSI sizes and not the architectural sizes. + */ + +#define MARGINX PCB_MIL_TO_COORD(500) +#define MARGINY PCB_MIL_TO_COORD(500) + +static MediaType media_data[] = { + {"A0", PCB_MM_TO_COORD(841), PCB_MM_TO_COORD(1189), MARGINX, MARGINY}, + {"A1", PCB_MM_TO_COORD(594), PCB_MM_TO_COORD(841), MARGINX, MARGINY}, + {"A2", PCB_MM_TO_COORD(420), PCB_MM_TO_COORD(594), MARGINX, MARGINY}, + {"A3", PCB_MM_TO_COORD(297), PCB_MM_TO_COORD(420), MARGINX, MARGINY}, + {"A4", PCB_MM_TO_COORD(210), PCB_MM_TO_COORD(297), MARGINX, MARGINY}, + {"A5", PCB_MM_TO_COORD(148), PCB_MM_TO_COORD(210), MARGINX, MARGINY}, + {"A6", PCB_MM_TO_COORD(105), PCB_MM_TO_COORD(148), MARGINX, MARGINY}, + {"A7", PCB_MM_TO_COORD(74), PCB_MM_TO_COORD(105), MARGINX, MARGINY}, + {"A8", PCB_MM_TO_COORD(52), PCB_MM_TO_COORD(74), MARGINX, MARGINY}, + {"A9", PCB_MM_TO_COORD(37), PCB_MM_TO_COORD(52), MARGINX, MARGINY}, + {"A10", PCB_MM_TO_COORD(26), PCB_MM_TO_COORD(37), MARGINX, MARGINY}, + {"B0", PCB_MM_TO_COORD(1000), PCB_MM_TO_COORD(1414), MARGINX, MARGINY}, + {"B1", PCB_MM_TO_COORD(707), PCB_MM_TO_COORD(1000), MARGINX, MARGINY}, + {"B2", PCB_MM_TO_COORD(500), PCB_MM_TO_COORD(707), MARGINX, MARGINY}, + {"B3", PCB_MM_TO_COORD(353), PCB_MM_TO_COORD(500), MARGINX, MARGINY}, + {"B4", PCB_MM_TO_COORD(250), PCB_MM_TO_COORD(353), MARGINX, MARGINY}, + {"B5", PCB_MM_TO_COORD(176), PCB_MM_TO_COORD(250), MARGINX, MARGINY}, + {"B6", PCB_MM_TO_COORD(125), PCB_MM_TO_COORD(176), MARGINX, MARGINY}, + {"B7", PCB_MM_TO_COORD(88), PCB_MM_TO_COORD(125), MARGINX, MARGINY}, + {"B8", PCB_MM_TO_COORD(62), PCB_MM_TO_COORD(88), MARGINX, MARGINY}, + {"B9", PCB_MM_TO_COORD(44), PCB_MM_TO_COORD(62), MARGINX, MARGINY}, + {"B10", PCB_MM_TO_COORD(31), PCB_MM_TO_COORD(44), MARGINX, MARGINY}, + {"Letter", PCB_INCH_TO_COORD(8.5), PCB_INCH_TO_COORD(11), MARGINX, MARGINY}, + {"11x17", PCB_INCH_TO_COORD(11), PCB_INCH_TO_COORD(17), MARGINX, MARGINY}, + {"Ledger", PCB_INCH_TO_COORD(17), PCB_INCH_TO_COORD(11), MARGINX, MARGINY}, + {"Legal", PCB_INCH_TO_COORD(8.5), PCB_INCH_TO_COORD(14), MARGINX, MARGINY}, + {"Executive", PCB_INCH_TO_COORD(7.5), PCB_INCH_TO_COORD(10), MARGINX, MARGINY}, + {"A-size", PCB_INCH_TO_COORD(8.5), PCB_INCH_TO_COORD(11), MARGINX, MARGINY}, + {"B-size", PCB_INCH_TO_COORD(11), PCB_INCH_TO_COORD(17), MARGINX, MARGINY}, + {"C-size", PCB_INCH_TO_COORD(17), PCB_INCH_TO_COORD(22), MARGINX, MARGINY}, + {"D-size", PCB_INCH_TO_COORD(22), PCB_INCH_TO_COORD(34), MARGINX, MARGINY}, + {"E-size", PCB_INCH_TO_COORD(34), PCB_INCH_TO_COORD(44), MARGINX, MARGINY}, + {"US-Business_Card", PCB_INCH_TO_COORD(3.5), PCB_INCH_TO_COORD(2.0), 0, 0}, + {"Intl-Business_Card", PCB_INCH_TO_COORD(3.375), PCB_INCH_TO_COORD(2.125), 0, 0} +}; + +#undef MARGINX +#undef MARGINY + +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 +Print a centering target in large drill holes. +@end ftable +%end-doc +*/ + {"drill-helper", "Print a centering target in large drill holes", + 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-bloat +@item --ps-bloat +Amount to add to trace/pad/pin edges. +@end ftable +%end-doc +*/ + {"ps-bloat", "Amount to add to trace/pad/pin edges", + PCB_HATT_COORD, -PCB_MIL_TO_COORD(100), PCB_MIL_TO_COORD(100), {0, 0, 0}, 0, 0}, +#define HA_psbloat 8 + +/* %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 9 + +/* %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}, medias, 0}, +#define HA_media 10 + +/* %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 11 + +/* %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 12 + +/* %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 13 + +/* %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 14 + +/* %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 15 + +/* %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 16 + +/* %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 17 + +/* %start-doc options "91 Postscript Export" +@ftable @code +@item --polygrid +If non-zero grid polygons instead of filling them with gridlines spaced as specified. +@end ftable +%end-doc +*/ + {"polygrid", "When non-zero: grid polygons instead of filling with gridlines spaced as specified", + PCB_HATT_REAL, 0, 10, {0, 0, 0.0}, 0, 0}, +#define HA_polygrid 18 + +}; + +#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_coord_t media_width, media_height, ps_width, ps_height; + + const char *filename; + pcb_bool drill_helper; + pcb_bool align_marks; + pcb_bool outline; + pcb_bool mirror; + pcb_bool fillpage; + pcb_bool automirror; + pcb_bool incolor; + pcb_bool doing_toc; + pcb_coord_t bloat; + pcb_bool invert; + int media_idx; + pcb_bool drillcopper; + pcb_bool legend; + + pcb_layer_t *outline_layer; + + 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; + + double polygrid; + + pcb_composite_op_t drawing_mode; +} global; + +static pcb_hid_attribute_t *ps_get_export_options(int *n) +{ + static char *last_made_filename = 0; + if (PCB) + pcb_derive_default_filename(PCB->Filename, &ps_attribute_list[HA_psfile], ".ps", &last_made_filename); + + 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->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", + media_data[global.media_idx].name, + 72 * PCB_COORD_TO_INCH(media_data[global.media_idx].Width), + 72 * PCB_COORD_TO_INCH(media_data[global.media_idx].Height)); + pcb_fprintf(f, "%%%%DocumentPaperSizes: %s\n", 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 (!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); + } + printf("PS: open %s\n", buf); + 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]; + pcb_layer_id_t lid; + + 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.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.bloat = options[HA_psbloat].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 = media_data[global.media_idx].Width; + global.media_height = media_data[global.media_idx].Height; + global.ps_width = global.media_width - 2.0 * media_data[global.media_idx].MarginX; + global.ps_height = global.media_height - 2.0 * media_data[global.media_idx].MarginY; + 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.polygrid = options[HA_polygrid].real_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); + } + + lid = -1; + pcb_layer_list(PCB, PCB_LYT_OUTLINE, &lid, 1); + if (lid >= 0) + global.outline_layer = pcb_get_layer(PCB->Data, lid); + else + global.outline_layer = NULL; + + 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, -1, 0, -1); + 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) { + /* %%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); + } + + global.pagecount = 1; /* Reset 'pagecount' if single file */ + global.doing_toc = 0; + ps_set_layer_group(-1, -1, 0, -1); /* reset static vars */ + pcb_hid_expose_all(&ps_hid, &global.exps); + + 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; + } + + global.filename = options[HA_psfile].str_value; + if (!global.filename) + global.filename = "pcb-out.ps"; + + global.multi_file = options[HA_multifile].int_value; + + if (global.multi_file) + fh = 0; + else { + fh = psopen(global.filename, "toc"); + if (!fh) { + perror(global.filename); + return; + } + } + + pcb_hid_save_and_show_layer_ons(save_ons); + ps_hid_export_to_file(fh, options); + pcb_hid_restore_layer_ons(save_ons); + + global.multi_file = 0; + if (fh) { + ps_end_file(fh); + fclose(fh); + } +} + +static void ps_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(ps_attribute_list, NUM_OPTIONS, ps_cookie, 0); + 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + char tmp_fn[PCB_PATH_MAX]; + char tmp_ln[PCB_PATH_MAX]; + static int lastgroup = -1; + time_t currenttime; + const char *name; + + if (is_empty == -1) { + lastgroup = -1; + return 0; + } + + if (flags & PCB_LYT_NOEXPORT) + return 0; + + if (flags & PCB_LYT_UI) + 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 (flags & PCB_LYT_CSECT) /* not yet finished */ + return 0; + + + name = pcb_layer_to_file_name(tmp_ln, layer, flags, PCB_FNS_fixed); + + global.is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + global.is_mask = !!(flags & PCB_LYT_MASK); + global.is_assy = !!(flags & PCB_LYT_ASSY); + 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->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.pagecount); + } + fprintf(global.f, "(%s) toc\n", name); + return 0; + } + + if (group < 0 || group != lastgroup) { + double boffset; + int mirror_this = 0; + lastgroup = group; + + if (global.pagecount != 0) { + pcb_fprintf(global.f, "showpage\n"); + } + global.pagecount++; + if (global.multi_file) { + if (global.f) { + ps_end_file(global.f); + fclose(global.f); + } + global.f = psopen(global.filename, pcb_layer_to_file_name(tmp_fn, layer, flags, PCB_FNS_fixed)); + 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, 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->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, PCB_FNS_fixed)); + else + fprintf(global.f, "30 41 moveto (%s) show\n", pcb_layer_to_file_name(tmp_fn, layer, flags, 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", (flags & PCB_LYT_FAB) ? 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 (flags & PCB_LYT_FAB) { + 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.outline && !global.outline_layer) ||global.invert) { + pcb_fprintf(global.f, + "0 setgray 0 setlinewidth 0 0 moveto 0 " + "%mi lineto %mi %mi lineto %mi 0 lineto closepath %s\n", + 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) PCB_MIN_PINORVIAHOLE, (pcb_coord_t) (PCB_MIN_PINORVIAHOLE * 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 (!(flags & PCB_LYT_FAB)) + 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 the 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.outline_layer != NULL && + global.outline_layer != pcb_get_layer(PCB->Data, layer) && + !(flags & PCB_LYT_OUTLINE)) { + int save_drill = global.is_drill; + global.is_drill = 0; + pcb_draw_layer(global.outline_layer, &global.exps.view); + 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 = Trace_Cap; + 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 char *name) +{ + if (global.drawing_mode == PCB_HID_COMP_NEGATIVE) { + gc->r = gc->g = gc->b = 255; + gc->erase = 0; + } + else if (strcmp(name, "erase") == 0 || strcmp(name, "drill") == 0) { + gc->r = gc->g = gc->b = 255; + gc->erase = 1; + } + else if (global.incolor) { + unsigned int r, g, b; + sscanf(name + 1, "%02x%02x%02x", &r, &g, &b); + gc->r = r; + gc->g = g; + gc->b = 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 + (gc->erase ? -2 : 2) * global.bloat); + global.linewidth = gc->width; + } + if (lastcap != gc->cap) { + int c; + switch (gc->cap) { + case Round_Cap: + case Trace_Cap: + c = 1; + break; + default: + case Square_Cap: + c = 2; + break; + } + 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 ? 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 == Square_Cap && (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 == Square_Cap) + 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 + 2 * global.bloat) / 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 >= PCB->minDrill / 4) + radius = PCB->minDrill / 4; + pcb_fprintf(global.f, "%mi %mi %mi c\n", cx, cy, radius + (gc->erase ? -1 : 1) * global.bloat); + } +} + +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; + double POLYGRID = ps_attribute_list[HA_polygrid].default_val.real_value; + + use_gc(gc); + + pl = poly->Clipped->contours; + len = 0; + if (POLYGRID > 0.1) + POLYGRID *= 1000000.0; + + do { + v = pl->head.next; + if (POLYGRID > 0.1) + fprintf(global.f, "closepath\n"); + 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); + + if (POLYGRID > 0.1) { + pcb_coord_t y, x, lx, ly, fx, fy, lsegs_xmin, lsegs_xmax, lsegs_ymin, lsegs_ymax; + lseg_t *lsegs = malloc(sizeof(lseg_t) * len); + pcb_coord_t *lpoints = malloc(sizeof(pcb_coord_t) * len); + int lsegs_used = 0; + + lsegs_xmin = -1000000000; + lsegs_ymin = -1000000000; + lsegs_xmax = +1000000000; + lsegs_ymax = +1000000000; + + /* save all line segs in an array */ + pl = poly->Clipped->contours; + do { + v = pl->head.next; + fx = v->point[0]; + fy = v->point[1]; + goto start1; + do { + lsegs_append(lx, ly, v->point[0], v->point[1]); + start1:; + lx = v->point[0]; + ly = v->point[1]; + } while ((v = v->next) != pl->head.next); + lsegs_append(lx, ly, fx, fy); + } while ((pl = pl->next) != NULL); + + + + + fprintf(global.f, "%% POLYGRID2\n"); + fprintf(global.f, "gsave\n"); + fprintf(global.f, "0.0015 setlinewidth\n"); + fprintf(global.f, "closepath\n"); + fprintf(global.f, "stroke\n"); + + for (y = lsegs_ymin; y < lsegs_ymax; y += POLYGRID) { + int pts, n; +/* pcb_fprintf(global.f, "%% gridline at y %mi\n", y);*/ + retry1:; + if (y > lsegs_ymax) + break; + pts = 0; + for (n = 0; n < lsegs_used; n++) { + if ((lsegs[n].y1 <= y) && (lsegs[n].y2 >= y)) { + if ((lsegs[n].y2 == lsegs[n].y1) || (lsegs[n].y1 == y) || (lsegs[n].y2 == y)) { + y += POLYGRID / 100.0; + goto retry1; + } + x = lsegs[n].x1 + (lsegs[n].x2 - lsegs[n].x1) * (y - lsegs[n].y1) / (lsegs[n].y2 - lsegs[n].y1); + lpoints[pts] = x; + pts++; + } + } + if ((pts % 2) != 0) { + y += POLYGRID / 100.0; + goto retry1; + } + if (pts > 1) { + qsort(lpoints, pts, sizeof(pcb_coord_t), coord_comp); + for (n = 0; n < pts; n += 2) + lseg_line(lpoints[n], y, lpoints[n + 1], y); + } + } + + for (x = lsegs_xmin; x < lsegs_xmax; x += POLYGRID) { + int pts, n; +/* pcb_fprintf(global.f, "%% gridline at y %mi\n", y); */ + retry2:; + if (x > lsegs_xmax) + break; + pts = 0; + for (n = 0; n < lsegs_used; n++) { + if (((lsegs[n].x1 <= x) && (lsegs[n].x2 >= x)) || ((lsegs[n].x1 >= x) && (lsegs[n].x2 <= x))) { + if ((lsegs[n].x2 == lsegs[n].x1) || (lsegs[n].x1 == x) || (lsegs[n].x2 == x)) { + x += POLYGRID / 100.0; + goto retry2; + } + y = lsegs[n].y1 + (lsegs[n].y2 - lsegs[n].y1) * (x - lsegs[n].x1) / (lsegs[n].x2 - lsegs[n].x1); + lpoints[pts] = y; + pts++; + } + } + if ((pts % 2) != 0) { + x += POLYGRID / 100.0; + goto retry2; + } + if ((pts > 1)) { + qsort(lpoints, pts, sizeof(pcb_coord_t), coord_comp); + for (n = 0; n < pts; n += 2) + lseg_line(x, lpoints[n], x, lpoints[n + 1]); + } + } + + + fprintf(global.f, "grestore\nnewpath\n"); + free(lsegs); + free(lpoints); + } + else + 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 = Round_Cap; + 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 - global.bloat, y1 - global.bloat, x2 + global.bloat, y2 + global.bloat); +} + +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_gui->attribute_dialog(ps_calib_attribute_list, 1, vals, _("Print Calibration Page"), _("Generates a printer calibration page"), 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(int x, int y, int action) +{ +} + +static int pcb_act_PSCalib(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + ps_calibrate(0.0, 0.0); + return 0; +} + +pcb_hid_action_t hidps_action_list[] = { + {"pscalib", 0, pcb_act_PSCalib} +}; + +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_hid_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) +{ + 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/1.2.7/src_plugins/export_ps/ps.h =================================================================== --- tags/1.2.7/src_plugins/export_ps/ps.h (nonexistent) +++ tags/1.2.7/src_plugins/export_ps/ps.h (revision 13657) @@ -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/1.2.7/src_plugins/export_stat/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_stat/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_stat/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_stat + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_stat/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_stat/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_stat/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_stat/export_stat.pup =================================================================== --- tags/1.2.7/src_plugins/export_stat/export_stat.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_stat/export_stat.pup (revision 13657) @@ -0,0 +1,8 @@ +$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 +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_stat/stat.c =================================================================== --- tags/1.2.7/src_plugins/export_stat/stat.c (nonexistent) +++ tags/1.2.7/src_plugins/export_stat/stat.c (revision 13657) @@ -0,0 +1,359 @@ + /* + * COPYRIGHT + * + * 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. + * + */ + +/* + * 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 "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_helper.h" +#include "hid_flags.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) +{ + static char *last_made_filename = 0; + const char *suffix = ".stat.lht"; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &stat_attribute_list[HA_statfile], suffix, &last_made_filename); + + 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; + + 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-v1 {\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++) { + pcb_cardinal_t m, terms = 0, best_terms = 0; + fprintf(f, " ha:%s {\n", pcb_netlist_names[nl]); + for(m = 0; m < PCB->NetlistLib[nl].MenuN; m++) { + pcb_lib_menu_t *menu = &PCB->NetlistLib[nl].Menu[m]; + terms += menu->EntryN; + if (menu->EntryN > best_terms) + best_terms = menu->EntryN; + } + fprintf(f, " nets=%ld\n", (long int)PCB->NetlistLib[nl].MenuN); + 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_ELEMENT_LOOP(PCB->Data) { + int pal, pil; + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, element)) + num_ebottom++; + else + num_etop++; + pal = padlist_length(&element->Pad); + pil = pinlist_length(&element->Pin); + if (pal > pil) + num_esmd++; + num_epads += pal; + num_epins += pil; + } + PCB_END_LOOP; + + + fprintf(f, " ha:board {\n"); + fprintf(f, " id={%s}\n", 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", PCB->MaxWidth); + pcb_fprintf(f, " height=%$mm\n", PCB->MaxHeight); + fprintf(f, " gross_area={%.4f mm^2}\n", (double)PCB_COORD_TO_MM(PCB->MaxWidth) * (double)PCB_COORD_TO_MM(PCB->MaxWidth)); + 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:elements {\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, " }\n"); + fprintf(f, " }\n"); + + fprintf(f, "}\n"); + fclose(f); +} + +static void 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); + 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) +{ +} + +int pplg_init_export_stat(void) +{ + 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/1.2.7/src_plugins/export_svg/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_svg/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_svg/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_svg + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_svg/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_svg/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_svg/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_svg/export_svg.pup =================================================================== --- tags/1.2.7/src_plugins/export_svg/export_svg.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_svg/export_svg.pup (revision 13657) @@ -0,0 +1,8 @@ +$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 +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/export_svg/svg.c =================================================================== --- tags/1.2.7/src_plugins/export_svg/svg.c (nonexistent) +++ tags/1.2.7/src_plugins/export_svg/svg.c (revision 13657) @@ -0,0 +1,845 @@ + /* + * COPYRIGHT + * + * 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. + * + */ + +/* + * 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 "error.h" +#include "layer.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "plugins.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_helper.h" +#include "hid_flags.h" + + +static pcb_hid_t svg_hid; + +const char *svg_cookie = "svg HID"; + + +typedef struct hid_gc_s { + 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 Trace_Cap: + case Round_Cap: + return "round"; + case Square_Cap: + return "square"; + case Beveled_Cap: + return "butt"; + } + 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 +}; + +#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) +{ + static char *last_made_filename = 0; + const char *suffix = ".svg"; + + if (PCB) + pcb_derive_default_filename(PCB->Filename, &svg_attribute_list[HA_svgfile], suffix, &last_made_filename); + + 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); + + 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_do_export(pcb_hid_attr_val_t * options) +{ + const char *filename; + int save_ons[PCB_MAX_LAYER + 2]; + int i; + pcb_coord_t w, h, x1, y1, x2, y2; + + 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; + } + + filename = options[HA_svgfile].str_value; + if (!filename) + filename = "pcb.svg"; + + f = pcb_fopen(filename, "wb"); + if (!f) { + perror(filename); + return; + } + + 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); + + pcb_hid_save_and_show_layer_ons(save_ons); + + svg_hid_export_to_file(f, options); + + pcb_hid_restore_layer_ons(save_ons); + + while(group_open) { + group_close(); + group_open--; + } + + fprintf(f, "\n"); + fclose(f); + f = NULL; +} + +static void 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); + pcb_hid_parse_command_line(argc, argv); +} + +static int svg_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + int opa, is_our_mask = 0, is_our_silk = 0; + + if (flags & PCB_LYT_UI) + return 0; + + 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) && !(flags & PCB_LYT_PDRILL) && !(flags & PCB_LYT_PDRILL) && !(flags & PCB_LYT_OUTLINE)) + 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, 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 = (flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL); + + 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 = Trace_Cap; + 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_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) + return "#FFFFFF"; + if (drawing_mode == PCB_HID_COMP_NEGATIVE) + return "#000000"; + return NULL; +} + +static void svg_set_color(pcb_hid_gc_t gc, const char *name) +{ + gc->drill = 0; + if (name == NULL) + name = "#ff0000"; + if (strcmp(name, "drill") == 0) { + name = "#ffffff"; + gc->drill = 1; + } + else if (strcmp(name, "erase") == 0) { +/* name = "#ffffff"; + gc->erase = 1;*/ + } + else 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.075; + + 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(int x, int 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) +{ + 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.holes_after = 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/1.2.7/src_plugins/export_test/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_test/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_test/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_export_test + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_test/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_test/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_test/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/export_test/export_test.c =================================================================== --- tags/1.2.7/src_plugins/export_test/export_test.c (nonexistent) +++ tags/1.2.7/src_plugins/export_test/export_test.c (revision 13657) @@ -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_helper.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) +{ + static char *last_export_test_filename = 0; + + if (PCB) { + pcb_derive_default_filename(PCB->Filename, &export_test_options[HA_export_testfile], ".export_test", &last_export_test_filename); + } + + 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 { +#warning 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 void 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); + 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) +{ + 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.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/1.2.7/src_plugins/export_test/export_test.pup =================================================================== --- tags/1.2.7/src_plugins/export_test/export_test.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_test/export_test.pup (revision 13657) @@ -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/1.2.7/src_plugins/export_xy/Makefile =================================================================== --- tags/1.2.7/src_plugins/export_xy/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/export_xy/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_xy + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/export_xy/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/export_xy/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/export_xy/Plug.tmpasm (revision 13657) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_xy} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_xy/xy.o @] + +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/1.2.7/src_plugins/export_xy/default_templ.h =================================================================== --- tags/1.2.7/src_plugins/export_xy/default_templ.h (nonexistent) +++ tags/1.2.7/src_plugins/export_xy/default_templ.h (revision 13657) @@ -0,0 +1,81 @@ +static const char *templ_xy_hdr = + "# $Id$\n" + "# PcbXY Version 1.0\n" + "# Date: %UTC%\n" + "# Author: %author%\n" + "# Title: %title% - PCB X-Y\n" + "# RefDes, Description, Value, X, Y, rotation, top/bottom\n" + "# X,Y in %suffix%. rotation in degrees.\n" + "# --------------------------------------------\n"; + +static const char *templ_xy_elem = + "%elem.name%,\"%elem.descr%\",\"%elem.value%\",%elem.x%,%elem.y%,%elem.rot%,%elem.side%\n"; + + +static const char *templ_gxyrs_hdr = + "#gxyrs version 1.0\n" + "#Date: %UTC%\n" + "#Author: %author%\n" + "#Title: %title% - pcb-rnd gxyrs\n" + "#Placement data:\n" + "#Designator X-Loc Y-Loc Rotation Side Type X-Size Y-Size Value Footprint\n" + "# --------------------------------------------\n"; + +static const char *templ_gxyrs_elem = + "%elem.name_% %elem.x% %elem.y% %elem.rot% %elem.side% %elem.pad_width% %elem.pad_height% %elem.value_% %elem.descr_%\n"; + +static const char *templ_macrofab_hdr = + "#pcb-rnd Macrofab export version 1.0\n" + "#Date: %UTC%\n" + "#Author: %author%\n" + "#Title: %title% - pcb-rnd Macrofab export\n" + "#Placement data:\n" + "#Designator X-Loc Y-Loc Rotation Side Type X-Size Y-Size Value Footprint\n" + "# --------------------------------------------\n"; + +static const char *templ_macrofab_elem = + "%elem.name_%\t%elem.padcx%\t%elem.padcy%\t%elem.rot%\t%elem.num-side%\t%elem.smdvsthru%\t%elem.pad_width_prerot%\t%elem.pad_height_prerot%\t%elem.value_%\t%elem.descr_%\n"; + +static const char *templ_TM220TM240_hdr = + "#pcb-rnd TM220A/TM240A xyrs version 1.0\n" + "#Date: %UTC%\n" + "#Author: %author%\n" + "#Title: %title% - pcb-rnd gxyrs\n" + "#Placement data:\n" + "#RefDes, top/bottom, X, Y, rotation\n" + "# X,Y in %suffix%. rotation in degrees.\n" + "# --------------------------------------------\n"; + +static const char *templ_TM220TM240_elem = + "%elem.name%,%elem.side%,%elem.x%,%elem.y%,%elem.rot%\n"; + +static const char *templ_KICADPOS_hdr = + "###pcb-rnd KiCad .pos compatible xyrs version 1.0\n" + "###Date: %UTC%, Author: %author%, Title: %title% - pcb-rnd gxyrs\n" + "## Unit = %suffix%., Angle = degrees.\n" + "#, Ref, Val, Package, PosX, PosY, Rot, Side\n"; + +static const char *templ_KICADPOS_elem = + ",\"%elem.name%\",\"%elem.value%\",\"%elem.descr%\",%elem.x%,%elem.y%,%elem.rot%,%elem.side%\n"; + +static const char *templ_NCAP_hdr = + "ncapture 0\n" + "4\n" + "%boardw%\n" + "%boardh%\n" + "80hmmm\n" + "-30hmmm\n"; + +static const char *templ_NCAP_elem = + "%elem.element_num%\n" + "0\n" + "%elem.pincount%\n" + "1\n" + "%elem.name%\n" + "%elem.90rot%\n" + "%elem.x%\n" + "%elem.y%\n" + "0\n"; + +static const char *templ_NCAP_pad = + "%pad.netname%\n"; Index: tags/1.2.7/src_plugins/export_xy/export_xy.pup =================================================================== --- tags/1.2.7/src_plugins/export_xy/export_xy.pup (nonexistent) +++ tags/1.2.7/src_plugins/export_xy/export_xy.pup (revision 13657) @@ -0,0 +1,13 @@ +$class export +$short xy (centroid) pcb_exporter +$long Template based export of XY centroid element data e.g. for pick & place. +$state works +$fmt-native no +$fmt-feature-w geda/PCB x;y +$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 +default buildin +dep export_bom +autoload 1 Index: tags/1.2.7/src_plugins/export_xy/xy.c =================================================================== --- tags/1.2.7/src_plugins/export_xy/xy.c (nonexistent) +++ tags/1.2.7/src_plugins/export_xy/xy.c (revision 13657) @@ -0,0 +1,846 @@ +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "math_helper.h" +#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 "obj_pinvia.h" +#include "netlist.h" +#include "safe_fs.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "hid_init.h" + +extern char *CleanBOMString(const char *in); + +const char *xy_cookie = "XY HID"; + +static const int verbose_rot = 0; + +static const char *format_names[] = { +#define FORMAT_XY 0 + "pcb xy", +#define FORMAT_GXYRS 1 + "gxyrs", +#define FORMAT_MACROFAB 2 + "Macrofab", +#define FORMAT_TM220TM240 3 + "TM220/TM240", +#define FORMAT_KICADPOS 4 + "KiCad .pos", +#define FORMAT_NCAP 5 + "ncap export (WIP)", + NULL +}; + + + +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}, format_names, 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; + +static pcb_hid_attribute_t *xy_get_export_options(int *n) +{ + static char *last_xy_filename = 0; + static int last_unit_value = -1; + + 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) + pcb_derive_default_filename(PCB->Filename, &xy_options[HA_xyfile], ".xy", &last_xy_filename); + + 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 + */ +static double xyToAngle(double x, double y, pcb_bool morethan2pins) +{ + double d = atan2(-y, x) * 180.0 / M_PI; + + if (verbose_rot) + pcb_trace(" xyToAngle: %f %f %d ->%f\n", x, y, morethan2pins, d); + + /* IPC 7351 defines different rules for 2 pin elements */ + if (morethan2pins) { + /* Multi pin case: + * Output 0 degrees if pin1 in is top left or top, i.e. between angles of + * 80 to 170 degrees. + * Pin #1 can be at dead top (e.g. certain PLCCs) or anywhere in the top + * left. + */ + if (d < -100) + return 90; /* -180 to -100 */ + else if (d < -10) + return 180; /* -100 to -10 */ + else if (d < 80) + return 270; /* -10 to 80 */ + else if (d < 170) + return 0; /* 80 to 170 */ + else + return 90; /* 170 to 180 */ + } + else { + /* 2 pin element: + * Output 0 degrees if pin #1 is in top left or left, i.e. in sector + * between angles of 95 and 185 degrees. + */ + if (d < -175) + return 0; /* -180 to -175 */ + else if (d < -85) + return 90; /* -175 to -85 */ + else if (d < 5) + return 180; /* -85 to 5 */ + else if (d < 95) + return 270; /* 5 to 95 */ + else + return 0; /* 95 to 180 */ + } +} + + + +/* + * In order of preference. + * Includes numbered and BGA pins. + * Possibly BGA pins can be missing, so we add a few to try. + */ +#define MAXREFPINS 32 /* max length of following list */ +static char *reference_pin_names[] = {"1", "2", "A1", "A2", "B1", "B2", 0}; + +typedef struct { + char utcTime[64]; + char *name, *descr, *value, *fixed_rotation; + const char *pad_netname; + pcb_coord_t x, y; + double theta, xray_theta; + pcb_element_t *element; + pcb_coord_t pad_cx, pad_cy; + pcb_coord_t pad_w, pad_h; + pcb_coord_t prpad_w, prpad_h; + int element_num; + pcb_coord_t ox, oy; + int origin_score; + char *origin_tmp; +} subst_ctx_t; + +/* Find the pick and place 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) +{ + subst_ctx_t *ctx = ctx_; + char *attr; + int score; + + /* first look for the format-specific attribute */ + attr = pcb_attribute_get(&line->Attributes, ctx->origin_tmp); + if (attr != NULL) { + score = 2; + goto found; + } + + /* then for the generic pnp-specific attribute */ + attr = pcb_attribute_get(&line->Attributes, "pnp-origin"); + if (attr != NULL) { + score = 1; + goto found; + } + return; + + found:; + if (score > ctx->origin_score) { + ctx->origin_score = score; + ctx->ox = (line->BoundingBox.X1 + line->BoundingBox.X2) / 2; + ctx->oy = (line->BoundingBox.Y1 + line->BoundingBox.Y2) / 2; + } +} + + +static void find_origin(subst_ctx_t *ctx, const char *format_name) +{ + char tmp[128]; + pcb_snprintf(tmp, sizeof(tmp), "pnp-origin-%s", format_name); + + ctx->origin_score = 0; + ctx->ox = ctx->oy = 0; + ctx->origin_tmp = tmp; + + pcb_loop_layers(PCB, ctx, NULL, find_origin_bump, NULL, NULL, NULL); +} + +static void calc_pad_bbox_(subst_ctx_t *ctx, pcb_element_t *element, pcb_coord_t *pw, pcb_coord_t *ph, pcb_coord_t *pcx, pcb_coord_t *pcy) +{ + pcb_box_t box, tmp; + box.X1 = box.Y1 = PCB_MAX_COORD; + box.X2 = box.Y2 = -PCB_MAX_COORD; + + PCB_PIN_LOOP(element); + { + pcb_pin_copper_bbox(&tmp, pin); + pcb_box_bump_box(&box, &tmp); + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + pcb_pad_copper_bbox(&tmp, pad); + pcb_box_bump_box(&box, &tmp); + } + PCB_END_LOOP; + + *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, pcb_element_t *element, int *pins, int *pads) +{ + *pins = *pads = 0; + + PCB_PIN_LOOP(element); + { + (*pins)++; + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + (*pads)++; + } + PCB_END_LOOP; +} + +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) { + /* this is what we would do if we wanted to return the pre-rotation state */ + if ((ctx->theta == 0) || (ctx->theta == 180)) { + calc_pad_bbox_(ctx, ctx->element, pw, ph, pcx, pcy); + return; + } + if ((ctx->theta == 90) || (ctx->theta == 270)) { + calc_pad_bbox_(ctx, ctx->element, ph, pw, pcx, pcy); + return; + } + pcb_message(PCB_MSG_ERROR, "XY can't calculate pad bbox for non-90-deg rotated elements yet\n"); + } + + calc_pad_bbox_(ctx, ctx->element, 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 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+%mS", xy_unit->allow, PCB->MaxWidth); + return 0; + } + if (strncmp(*input, "boardh%", 7) == 0) { + *input += 7; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, PCB->MaxHeight); + return 0; + } + if (strncmp(*input, "elem.", 5) == 0) { + *input += 5; + if (strncmp(*input, "name%", 5) == 0) { + *input += 5; + gds_append_str(s, ctx->name); + return 0; + } + if (strncmp(*input, "name_%", 6) == 0) { + *input += 6; + append_clean(s, ctx->name); + return 0; + } + if (strncmp(*input, "descr%", 6) == 0) { + *input += 6; + gds_append_str(s, ctx->descr); + return 0; + } + if (strncmp(*input, "descr_%", 7) == 0) { + *input += 7; + 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+%mS", xy_unit->allow, ctx->x); + return 0; + } + if (strncmp(*input, "y%", 2) == 0) { + *input += 2; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->y); + return 0; + } + if (strncmp(*input, "padcx%", 6) == 0) { + *input += 6; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->pad_cx); + return 0; + } + if (strncmp(*input, "padcy%", 6) == 0) { + *input += 6; + pcb_append_printf(s, "%m+%mS", 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, PCB_FRONT(ctx->element) == 1 ? "top" : "bottom"); + return 0; + } + if (strncmp(*input, "element_num%", 12) == 0) { + *input += 12; + pcb_append_printf(s, "%d", ctx->element_num); + return 0; + } + if (strncmp(*input, "num-side%", 9) == 0) { + *input += 9; + gds_append_str(s, PCB_FRONT(ctx->element) == 1 ? "1" : "2"); + return 0; + } + if (strncmp(*input, "pad_width%", 10) == 0) { + *input += 10; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->pad_w); + return 0; + } + if (strncmp(*input, "pad_height%", 11) == 0) { + *input += 11; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->pad_h); + return 0; + } + if (strncmp(*input, "pad_width_prerot%", 17) == 0) { + *input += 17; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->prpad_w); + return 0; + } + if (strncmp(*input, "pad_height_prerot%", 18) == 0) { + *input += 18; + pcb_append_printf(s, "%m+%mS", xy_unit->allow, ctx->prpad_h); + return 0; + } + if (strncmp(*input, "smdvsthru%", 10) == 0) { + *input += 10; + count_pins_pads(ctx, ctx->element, &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, "pincount%", 9) == 0) { + *input += 9; + count_pins_pads(ctx, ctx->element, &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, "pad.", 4) == 0) { + *input += 4; + 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, *elem, *pad, *foot; +} template_t; + +static int PrintXY(const template_t *templ, const char *format_name) +{ + double sumx, sumy; + double pin1x = 0.0, pin1y = 0.0; + int pin_cnt; + FILE *fp; + int pinfound[MAXREFPINS]; + double pinx[MAXREFPINS]; + double piny[MAXREFPINS]; + double pinangle[MAXREFPINS]; + double padcentrex, padcentrey; + double centroidx, centroidy; + int found_any_not_at_centroid, found_any, rpindex; + subst_ctx_t ctx; + + fp = pcb_fopen(xy_filename, "w"); + if (!fp) { + pcb_gui->log("Cannot open file %s for writing\n", xy_filename); + return 1; + } + + ctx.theta = 0; + ctx.element_num = 0; + + pcb_print_utc(ctx.utcTime, sizeof(ctx.utcTime), 0); + + find_origin(&ctx, format_name); + + fprintf_templ(fp, &ctx, templ->hdr); + + /* + * For each element we calculate the centroid of the footprint. + */ + + PCB_ELEMENT_LOOP(PCB->Data); + { + /* initialize our pin count and our totals for finding the + centriod */ + pin_cnt = 0; + sumx = 0.0; + sumy = 0.0; + ctx.pad_w = ctx.pad_h = 0; + ctx.element_num++; + + /* + * iterate over the pins and pads keeping a running count of how + * many pins/pads total and the sum of x and y coordinates + * + * While we're at it, store the location of pin/pad #1 and #2 if + * we can find them + */ + + PCB_PIN_LOOP(element); + { + sumx += (double) pin->X; + sumy += (double) pin->Y; + pin_cnt++; + + for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { + if (PCB_NSTRCMP(pin->Number, reference_pin_names[rpindex]) == 0) { + pinx[rpindex] = (double) pin->X; + piny[rpindex] = (double) pin->Y; + pinangle[rpindex] = 0.0; /* pins have no notion of angle */ + pinfound[rpindex] = 1; + } + } + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + sumx += (pad->Point1.X + pad->Point2.X) / 2.0; + sumy += (pad->Point1.Y + pad->Point2.Y) / 2.0; + pin_cnt++; + + for (rpindex = 0; reference_pin_names[rpindex]; rpindex++) { + if (PCB_NSTRCMP(pad->Number, reference_pin_names[rpindex]) == 0) { + padcentrex = (double) (pad->Point1.X + pad->Point2.X) / 2.0; + padcentrey = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; + pinx[rpindex] = padcentrex; + piny[rpindex] = padcentrey; + /* + * NOTE: We swap the Y points because in PCB, the Y-axis + * is inverted. Increasing Y moves down. We want to deal + * in the usual increasing Y moves up coordinates though. + */ + pinangle[rpindex] = (180.0 / M_PI) * atan2(pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); + pinfound[rpindex] = 1; + } + } + } + PCB_END_LOOP; + + if (pin_cnt > 0) { + centroidx = sumx / (double) pin_cnt; + centroidy = sumy / (double) pin_cnt; + + if (PCB_NSTRCMP(pcb_attribute_get(&element->Attributes, "xy-centre"), "origin") == 0) { + ctx.x = element->MarkX; + ctx.y = element->MarkY; + } + else { + ctx.x = centroidx; + ctx.y = centroidy; + } + + ctx.fixed_rotation = pcb_attribute_get(&element->Attributes, "xy-fixed-rotation"); + if (ctx.fixed_rotation) { + /* The user specified a fixed rotation */ + ctx.theta = atof(ctx.fixed_rotation); + found_any_not_at_centroid = 1; + found_any = 1; + } + else { + /* Find first reference pin not at the centroid */ + found_any_not_at_centroid = 0; + found_any = 0; + ctx.theta = 0.0; + for (rpindex = 0; reference_pin_names[rpindex] && !found_any_not_at_centroid; rpindex++) { + if (pinfound[rpindex]) { + found_any = 1; + + /* Recenter pin "#1" onto the axis which cross at the part + centroid */ + pin1x = pinx[rpindex] - ctx.x; + pin1y = piny[rpindex] - ctx.y; + + if (verbose_rot) + pcb_trace("\nxy rot: %s pin_cnt=%d pin1x=%d pin1y=%d\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), pin_cnt, pin1x, pin1y); + + /* if only 1 pin, use pin 1's angle */ + if (pin_cnt == 1) { + ctx.theta = pinangle[rpindex]; + found_any_not_at_centroid = 1; + } + else { + if ((pin1x != 0.0) || (pin1y != 0.0)) + ctx.xray_theta = xyToAngle(pin1x, pin1y, pin_cnt > 2); + + /* flip x, to reverse rotation for elements on back */ + if (PCB_FRONT(element) != 1) + pin1x = -pin1x; + + if ((pin1x != 0.0) || (pin1y != 0.0)) { + ctx.theta = xyToAngle(pin1x, pin1y, pin_cnt > 2); + found_any_not_at_centroid = 1; + } + } + if (verbose_rot) + pcb_trace(" ->theta=%f\n", ctx.theta); + } + } + + if (!found_any) { + pcb_message + (PCB_MSG_WARNING, "PrintXY(): unable to figure out angle because I could\n" + " not find a suitable reference pin of element %s\n" + " Setting to %g degrees\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), ctx.theta); + } + else if (!found_any_not_at_centroid) { + pcb_message + (PCB_MSG_WARNING, "PrintXY(): unable to figure out angle of element\n" + " %s because the reference pin(s) are at the centroid of the part.\n" + " Setting to %g degrees\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), ctx.theta); + } + } + } + + + ctx.name = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element))); + ctx.descr = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element))); + ctx.value = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_VALUE(element))); + + xy_translate(&ctx, &ctx.x, &ctx.y); + + ctx.element = element; + 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->elem); + + PCB_PIN_LOOP(element); + { + pcb_lib_menu_t *m = pcb_netlist_find_net4pin(PCB, pin); + if (m != NULL) + ctx.pad_netname = m->Name; + else + ctx.pad_netname = NULL; + fprintf_templ(fp, &ctx, templ->pad); + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + pcb_lib_menu_t *m = pcb_netlist_find_net4pad(PCB, pad); + if (m != NULL) + ctx.pad_netname = m->Name; + else + ctx.pad_netname = NULL; + fprintf_templ(fp, &ctx, templ->pad); + } + PCB_END_LOOP; + + 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); +} + +#include "default_templ.h" + +static void xy_do_export(pcb_hid_attr_val_t * options) +{ + int i; + template_t templ; + + memset(&templ, 0, sizeof(templ)); + + 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 = &get_unit_list()[options[HA_unit].int_value]; + + + switch(options[HA_format].int_value) { + case FORMAT_XY: + templ.hdr = templ_xy_hdr; + templ.elem = templ_xy_elem; + break; + case FORMAT_GXYRS: + templ.hdr = templ_gxyrs_hdr; + templ.elem = templ_gxyrs_elem; + break; + case FORMAT_MACROFAB: + xy_unit = get_unit_struct("mil"); /* Macrofab requires mils */ + templ.hdr = templ_macrofab_hdr; + templ.elem = templ_macrofab_elem; + break; + case FORMAT_TM220TM240: + templ.hdr = templ_TM220TM240_hdr; + templ.elem = templ_TM220TM240_elem; + break; + case FORMAT_KICADPOS: + templ.hdr = templ_KICADPOS_hdr; + templ.elem = templ_KICADPOS_elem; + break; + case FORMAT_NCAP: + templ.hdr = templ_NCAP_hdr; + templ.elem = templ_NCAP_elem; + templ.pad = templ_NCAP_pad; + break; + default: + pcb_message(PCB_MSG_ERROR, "Invalid format\n"); + return; + } + + 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 void xy_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_register_attributes(xy_options, sizeof(xy_options) / sizeof(xy_options[0]), xy_cookie, 0); + 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); +} + +int pplg_init_export_xy(void) +{ + memset(&xy_hid, 0, sizeof(pcb_hid_t)); + + 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); + return 0; +} Index: tags/1.2.7/src_plugins/extedit/Makefile =================================================================== --- tags/1.2.7/src_plugins/extedit/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/extedit/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_extedit + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/extedit/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/extedit/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/extedit/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/extedit/extedit.c =================================================================== --- tags/1.2.7/src_plugins/extedit/extedit.c (nonexistent) +++ tags/1.2.7/src_plugins/extedit/extedit.c (revision 13657) @@ -0,0 +1,308 @@ +/* + * 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. + * + */ + +#include "config.h" + +#include "hid.h" +#include "hid_attrib.h" +#include "hid_actions.h" +#include "hid_dad.h" +#include "action_helper.h" + +#include "board.h" +#include "compat_fs.h" +#include "compat_misc.h" +#include "const.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_TYPE_SUBC | PCB_TYPE_ELEMENT, EEF_LIHATA, "pcb-rnd \"%f\""}, + {"editor", PCB_TYPE_SUBC | PCB_TYPE_ELEMENT, EEF_LIHATA, "xterm -e editor \"%f\""}, + {NULL, 0, 0, NULL} +}; + +/* accept these objects for external editing */ +#define EXTEDIT_TYPES (PCB_TYPE_SUBC | PCB_TYPE_ELEMENT) + +#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) { + pcb_gui->unwatch_file(ctx->wid); + ctx->stay = 0; + return pcb_false; + } + 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_gui->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_gui->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); + } + } + fclose(fc); + + if (pcb_gui != NULL) + pcb_gui->progress(0, 0, NULL); + free(cmd); +} + + + +static const char pcb_acts_extedit[] = "extedit(object|selected, [interactive|method])\n"; +static const char pcb_acth_extedit[] = "Invoke an external program to edit a specific part of the current board."; +static int pcb_act_extedit(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + long type; + void *ptr1, *ptr2, *ptr3; + extedit_method_t *mth = NULL; + char *tmp_fn; + int ret = 1; + FILE *f; + + /* pick up the object to edit */ + if ((argc == 0) || (pcb_strcasecmp(argv[0], "object") == 0)) { + pcb_gui->get_coords("Click on object to edit", &x, &y); + type = pcb_search_screen(x, y, EXTEDIT_TYPES, &ptr1, &ptr2, &ptr3); + } + else if ((argc > 0) && (pcb_strcasecmp(argv[0], "selected") == 0)) { +#warning TODO + pcb_message(PCB_MSG_ERROR, "\"Selected\" not supported yet\n"); + return 1; + } + else { + pcb_message(PCB_MSG_ERROR, "Wrong 1st argument '%s'\n", argv[0]); + return 1; + } + + /* determine the method */ + if (argc > 1) { + for(mth = methods; mth->name != NULL; mth++) { + if (pcb_strcasecmp(mth->name, argv[1]) == 0) + break; + } + if (mth->name == NULL) { + pcb_message(PCB_MSG_ERROR, "unknown method '%s'; available methods:\n", argv[1]); + 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"); + return 1; + } + } + if (mth == NULL) { + mth = extedit_interactive(); + if (mth == NULL) /* no method selected */ + return 1; + } + + tmp_fn = pcb_tempfile_name_new("extedit"); + if (tmp_fn == NULL) { + pcb_message(PCB_MSG_ERROR, "Failed to create temporary file\n"); + return 1; + } + + /* export */ + switch(mth->fmt) { + case EEF_LIHATA: + { + int bn =PCB_MAX_BUFFER - 1; + + 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 quit1; + } + + 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_v4, 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 =PCB_MAX_BUFFER - 1; + + pcb_buffer_set_number(bn); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + + if (io_lihata_parse_element(&plug_io_lihata_v4, 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); + goto quit0; + } + + pcb_undo_save_serial(); + pcb_buffer_copy_to_layout(PCB, 0, 0); + 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:; + return ret; +} + +static pcb_hid_action_t extedit_action_list[] = { + {"extedit", 0, 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_hid_remove_actions_by_cookie(extedit_cookie); +} + +#include "dolists.h" +int pplg_init_extedit(void) +{ + PCB_REGISTER_ACTIONS(extedit_action_list, extedit_cookie) + return 0; +} Index: tags/1.2.7/src_plugins/extedit/extedit.pup =================================================================== --- tags/1.2.7/src_plugins/extedit/extedit.pup (nonexistent) +++ tags/1.2.7/src_plugins/extedit/extedit.pup (revision 13657) @@ -0,0 +1,7 @@ +$class feature +$short edit with external program +$long invoke external program to edit parts of the current board +$state works +dep io_lihata +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/extedit/extedit_dad.c =================================================================== --- tags/1.2.7/src_plugins/extedit/extedit_dad.c (nonexistent) +++ tags/1.2.7/src_plugins/extedit/extedit_dad.c (revision 13657) @@ -0,0 +1,129 @@ +/* + * 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. + * + */ + +#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, 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); + + /* default value string crashes for some reason, disable it for now */ + pcb_gui->attr_dlg_widget_state(ee->dlg_hid_ctx, ee->wcmd, 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; + + 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_END(ee.dlg); + + PCB_DAD_NEW(ee.dlg, "External editor", "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/1.2.7/src_plugins/fontmode/Makefile =================================================================== --- tags/1.2.7/src_plugins/fontmode/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/fontmode/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fontmode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/fontmode/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/fontmode/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/fontmode/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/fontmode/fontmode.c =================================================================== --- tags/1.2.7/src_plugins/fontmode/fontmode.c (nonexistent) +++ tags/1.2.7/src_plugins/fontmode/fontmode.c (revision 13657) @@ -0,0 +1,375 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * 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 "hid_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 fontedit_syntax[] = "FontEdit()"; + +static const char fontedit_help[] = "Convert the current font to a PCB for editing."; + +/* %start-doc actions FontEdit + +%end-doc */ + +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); + 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 int FontEdit(int argc, const char **argv, pcb_coord_t Ux, pcb_coord_t Uy) +{ + 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_hid_actionl("New", "Font", 0)) + return 1; + +#warning TODO do we need to change design.bloat here? + conf_set(CFR_DESIGN, "editor/grid_unit", -1, "mil", POL_OVERWRITE); + conf_set_design("design/bloat", "%s", "1"); PCB->Bloat = 1; + conf_set_design("design/shrink", "%s", "1"); PCB->Shrink = 1; + conf_set_design("design/min_wid", "%s", "1"); PCB->minWid = 1; + conf_set_design("design/min_slk", "%s", "1"); PCB->minSlk = 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->LayerGroups); + 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, 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, 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()); + 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()); + 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()); + } + return 0; +} + +static const char fontsave_syntax[] = "FontSave()"; + +static const char fontsave_help[] = "Convert the current PCB back to a font."; + +/* %start-doc actions FontSave + +%end-doc */ + +static int FontSave(int argc, const char **argv, pcb_coord_t Ux, pcb_coord_t Uy) +{ + 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_hid_actionl("SaveFontTo", NULL); + + return 0; +} + +pcb_hid_action_t fontmode_action_list[] = { + {"FontEdit", 0, FontEdit, + fontedit_help, fontedit_syntax} + , + {"FontSave", 0, FontSave, + fontsave_help, fontsave_syntax} +}; + +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_hid_remove_actions_by_cookie(fontmode_cookie); +} + +#include "dolists.h" +int pplg_init_fontmode(void) +{ + PCB_REGISTER_ACTIONS(fontmode_action_list, fontmode_cookie) + return 0; +} Index: tags/1.2.7/src_plugins/fontmode/fontmode.pup =================================================================== --- tags/1.2.7/src_plugins/fontmode/fontmode.pup (nonexistent) +++ tags/1.2.7/src_plugins/fontmode/fontmode.pup (revision 13657) @@ -0,0 +1,6 @@ +$class feature +$short font editor +$long Font editing actions. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/fp_board/Makefile =================================================================== --- tags/1.2.7/src_plugins/fp_board/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/fp_board/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_board + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/fp_board/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/fp_board/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/fp_board/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/fp_board/fp_board.c =================================================================== --- tags/1.2.7/src_plugins/fp_board/fp_board.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_board/fp_board.c (revision 13657) @@ -0,0 +1,172 @@ + +#include "config.h" + +#include "plugins.h" +#include "plug_footprint.h" +#include "board.h" +#include "buffer.h" +#include "data.h" +#include "error.h" +#include "obj_elem.h" +#include "obj_elem_list.h" +#include "obj_elem_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; + elementlist_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 */ + id = 0; + PCB_ELEMENT_LOOP(buff.Data) { + const char *ename; + pcb_fplibrary_t *e; + + id++; + elementlist_dedup_skip(dedup, element); + + ename = element->Name[PCB_ELEMNAME_IDX_DESCRIPTION].TextString; + 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; + + elementlist_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) +{ + char *fpath, *ids, *end; + unsigned long int id, req_id; + pcb_buffer_t buff; + FILE *f = NULL; + pcb_opctx_t op; + char *tmp_name = ".board.fp"; + + 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_ELEMENT_LOOP(buff.Data) { + id++; + if (id == req_id) { +/* if (strcmp(element->Name[PCB_ELEMNAME_IDX_DESCRIPTION].TextString, l->name)) */ + pcb_buffer_t buff2; + +#warning TODO: extend the API: + /* This is not pretty: we are saving the element to a file so we can return a FILE *. + Later on we should just return the footprint. */ + memset(&op, 0, sizeof(op)); + op.buffer.dst = calloc(sizeof(pcb_data_t), 1); + pcb_data_set_layer_parents(op.buffer.dst); + pcb_elemop_add_to_buffer(&op, element); + + f = pcb_fopen(tmp_name, "w"); + memset(&buff2, 0, sizeof(buff2)); + buff2.Data = op.buffer.dst; + pcb_write_buffer(f, &buff2, "pcb", pcb_true); + fclose(f); + + pcb_data_free(op.buffer.dst); + free(op.buffer.dst); + + f = pcb_fopen(tmp_name, "r"); + break; + } + } PCB_END_LOOP; + + /* clean up buffer */ + + pcb_buffer_clear(PCB, &buff); + free(buff.Data); + return f; + +err:; + free(fpath); + return NULL; +} + +static void fp_board_fclose(pcb_plug_fp_t *ctx, FILE * f, pcb_fp_fopen_ctx_t *fctx) +{ + fclose(f); +#warning TODO: remove file +} + + +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) +{ + 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/1.2.7/src_plugins/fp_board/fp_board.pup =================================================================== --- tags/1.2.7/src_plugins/fp_board/fp_board.pup (nonexistent) +++ tags/1.2.7/src_plugins/fp_board/fp_board.pup (revision 13657) @@ -0,0 +1,6 @@ +$class fp +$short footprint library from boards +$long Footprint: load a board and expose all the unique elements on that board as a footprint library +$state WIP +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/fp_fs/Makefile =================================================================== --- tags/1.2.7/src_plugins/fp_fs/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/fp_fs/Makefile (revision 13657) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_fs + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.7/src_plugins/fp_fs/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/fp_fs/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/fp_fs/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/fp_fs/fp_fs.c =================================================================== --- tags/1.2.7/src_plugins/fp_fs/fp_fs.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_fs/fp_fs.c (revision 13657) @@ -0,0 +1,539 @@ +/* + * COPYRIGHT + * + * 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ +#include "config.h" + +#ifdef HAVE_UNISTD_H +#include +#endif + +#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 "compat_nls.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. + */ + 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); + + /* Return error if the root is not a directory, to give other fp_ plugins a chance */ + if ((is_root) && (!pcb_is_dir(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) + end = p + strlen(p); + memcpy(path, p, end - p); + path[end - p] = '\0'; + + pcb_path_resolve(path, &fpath, 0); +/* 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; +} + +#warning subc TODO: 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; + + 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')) { + 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; + } + } + 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 +static FILE *fp_fs_fopen(pcb_plug_fp_t *ctx, const char *path, const char *name, pcb_fp_fopen_ctx_t *fctx) +{ + char *basename, *params, *fullname; + FILE *f = NULL; + const char *libshell; + + pcb_conf_cmd_is_safe(rc.library_shell, &libshell, 1); + + 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 = " "; + 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);*/ + f = pcb_popen(cmd, "r"); + 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) +{ + if (fctx->field[F_IS_PARAMETRIC].i) + pcb_pclose(f); + else + fclose(f); +} + + +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) +{ + 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/1.2.7/src_plugins/fp_fs/fp_fs.pup =================================================================== --- tags/1.2.7/src_plugins/fp_fs/fp_fs.pup (nonexistent) +++ tags/1.2.7/src_plugins/fp_fs/fp_fs.pup (revision 13657) @@ -0,0 +1,6 @@ +$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 +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/fp_wget/Makefile =================================================================== --- tags/1.2.7/src_plugins/fp_wget/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/Makefile (revision 13657) @@ -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/1.2.7/src_plugins/fp_wget/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/fp_wget/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/Plug.tmpasm (revision 13657) @@ -0,0 +1,14 @@ +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} + +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/1.2.7/src_plugins/fp_wget/edakrill.c =================================================================== --- tags/1.2.7/src_plugins/fp_wget/edakrill.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/edakrill.c (revision 13657) @@ -0,0 +1,265 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "wget_common.h" +#include "edakrill.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "compat_misc.h" +#include "safe_fs.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"; +static const char *gedasym_cache = "fp_wget_cache"; +static const char *last_sum_fn = "fp_wget_cache/edakrill.last"; + +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; + + if (strncmp(path, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return -1; + + 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, gedasym_cache, &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, gedasym_cache, &f, &fctx, mode) != 0) { + printf("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); + + printf("update!\n"); + + 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) +{ + gds_t s; + FILE *f; + + if (strncmp(name, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) == 0) + name+=strlen(REQUIRE_PATH_PREFIX); + else + return NULL; + + if (*name == '/') + name++; + + gds_init(&s); + gds_append_str(&s, FP_URL); + gds_append_str(&s, name); + + fp_wget_open(s.array, gedasym_cache, &f, &(fctx->field[FIELD_WGET_CTX].i), FP_WGET_UPDATE); + + fctx->backend = ctx; + + gds_uninit(&s); + 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/1.2.7/src_plugins/fp_wget/edakrill.h =================================================================== --- tags/1.2.7/src_plugins/fp_wget/edakrill.h (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/edakrill.h (revision 13657) @@ -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); +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/1.2.7/src_plugins/fp_wget/fp_wget.c =================================================================== --- tags/1.2.7/src_plugins/fp_wget/fp_wget.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/fp_wget.c (revision 13657) @@ -0,0 +1,27 @@ +#include "config.h" +#include "gedasymbols.h" +#include "edakrill.h" +#include "plugins.h" +#include "fp_wget_conf.h" + +conf_fp_wget_t conf_fp_wget; + +int pplg_check_ver_fp_wget(int ver_needed) { return 0; } + +void pplg_uninit_fp_wget(void) +{ + fp_gedasymbols_uninit(); + fp_edakrill_uninit(); + conf_unreg_fields("plugins/fp_wget/"); +} + +int pplg_init_fp_wget(void) +{ +#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" + + fp_gedasymbols_init(); + fp_edakrill_init(); + return 0; +} Index: tags/1.2.7/src_plugins/fp_wget/fp_wget.pup =================================================================== --- tags/1.2.7/src_plugins/fp_wget/fp_wget.pup (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/fp_wget.pup (revision 13657) @@ -0,0 +1,7 @@ +$class fp +$short web footprints +$long Footprint: get static (file) footprints from the web, e.g. from http://gedasymbols.org +$state works +default buildin +dep fp_fs +autoload 1 Index: tags/1.2.7/src_plugins/fp_wget/fp_wget_conf.h =================================================================== --- tags/1.2.7/src_plugins/fp_wget/fp_wget_conf.h (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/fp_wget_conf.h (revision 13657) @@ -0,0 +1,17 @@ +#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 */ + } fp_wget; + } plugins; +} conf_fp_wget_t; + +extern conf_fp_wget_t conf_fp_wget; + +#endif Index: tags/1.2.7/src_plugins/fp_wget/gedasymbols.c =================================================================== --- tags/1.2.7/src_plugins/fp_wget/gedasymbols.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/gedasymbols.c (revision 13657) @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "wget_common.h" +#include "gedasymbols.h" +#include "plugins.h" +#include "plug_footprint.h" +#include "compat_misc.h" +#include "safe_fs.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; +static const char *gedasym_cache = "fp_wget_cache"; +static const char *last_sum_fn = "fp_wget_cache/gedasymbols.last"; + +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; + + if (strncmp(path, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) != 0) + return -1; + + 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, gedasym_cache, &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, gedasym_cache, &f, &fctx, mode) != 0) { + printf("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); + + printf("update!\n"); + + 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) +{ + gds_t s; + FILE *f; + + if (strncmp(name, REQUIRE_PATH_PREFIX, strlen(REQUIRE_PATH_PREFIX)) == 0) + name+=strlen(REQUIRE_PATH_PREFIX); + else + return NULL; + + if (*name == '/') + name++; + + 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, gedasym_cache, &f, &(fctx->field[FIELD_WGET_CTX].i), FP_WGET_UPDATE); + + fctx->backend = ctx; + + gds_uninit(&s); + 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/1.2.7/src_plugins/fp_wget/gedasymbols.h =================================================================== --- tags/1.2.7/src_plugins/fp_wget/gedasymbols.h (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/gedasymbols.h (revision 13657) @@ -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); +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/1.2.7/src_plugins/fp_wget/tester.c =================================================================== --- tags/1.2.7/src_plugins/fp_wget/tester.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/tester.c (revision 13657) @@ -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/1.2.7/src_plugins/fp_wget/wget_common.c =================================================================== --- tags/1.2.7/src_plugins/fp_wget/wget_common.c (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/wget_common.c (revision 13657) @@ -0,0 +1,158 @@ +#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)) { + sprintf(cmd, "%s -O '%s/%s' %s '%s'", wget_cmd, cache_path, cdir, upds, url); + if (pcb_system(cmd) != 0) { + /* 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; +} Index: tags/1.2.7/src_plugins/fp_wget/wget_common.h =================================================================== --- tags/1.2.7/src_plugins/fp_wget/wget_common.h (nonexistent) +++ tags/1.2.7/src_plugins/fp_wget/wget_common.h (revision 13657) @@ -0,0 +1,12 @@ +#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); Index: tags/1.2.7/src_plugins/gpmi/Makefile =================================================================== --- tags/1.2.7/src_plugins/gpmi/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_pcb_gpmi + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/gpmi/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/gpmi/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/Plug.tmpasm (revision 13657) @@ -0,0 +1,104 @@ +append /local/pcb/pcb_gpmi/enable {} +append /local/pcb/pcb_gpmi/buildin {} + +switch /local/pcb/gpmi/controls +case {disable} + put /local/pcb/TOPVARS {} + put /local/pcb/CLEANRULES {} + end +default + + +append /local/pcb/RULES [@ +### gpmi_plugin +clean_gpmi: FORCE + cd $(PCB_GPMI) && make clean + +$(PLUGIDIR)/pcb-rnd-gpmi: $(PCB_GPMI)/gpmi_plugin/gpmi_plugin.o FORCE + $(MKDIR) $(PLUGIDIR) + $(MKDIR) $(PLUGIDIR)/pcb-rnd-gpmi + $(CP) $(PLUGDIR)/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/*.so $(PLUGIDIR)/pcb-rnd-gpmi + +# HACK: the gpmi plugin, for historical reasons, have an own build system, +# need to go there to properly build it with prefixes. +$(PCB_GPMI)/gpmi_plugin/gpmi_plugin.o: + cd $(PCB_GPMI)/gpmi_plugin && make +@] + + +append /local/pcb/all [@ $(PLUGIDIR)/pcb-rnd-gpmi @] + +append /local/pcb/CLEANRULES {clean_gpmi} + +append /local/pcb/TOPVARS [@ +PCB_GPMI=$(PLUGDIR)/gpmi/pcb-gpmi +@] + +append /local/pcb/rules/install { cd $(PCB_GPMI) && make install} { +} +append /local/pcb/rules/linstall { cd $(PCB_GPMI) && make linstall} { +} +append /local/pcb/rules/uninstall { cd $(PCB_GPMI) && make uninstall} { +} +end +end + + +switch /local/pcb/gpmi/controls + case {buildin} + append /local/pcb/buildin_pups [@gpmi=gpmi/gpmi.pup@] {\n} + append /local/pcb/RULES [@ + +mod_pcb_gpmi: all + +@] + + append /local/pcb/LIBS_PRE {$(PCB_GPMI)/gpmi_plugin/gpmi_buildin.a} + append /local/pcb/EXEDEPS {$(PCB_GPMI)/gpmi_plugin/gpmi_buildin.a} + append /local/pcb/LIBS /target/libs/script/gpmi/ldflags + + append /local/pcb/buildin_init_extern [@extern pcb_uninit_t hid_gpmi_init();@] {\n} + + + append /local/pcb/buildin_init_code [@ + uninit_func = hid_gpmi_init(); + pcb_plugin_register("gpmi", "", NULL, 0, uninit_func); +@] {\n} + + +# append /local/pcb/CFLAGS /target/libs/script/gpmi/cflags +# append /local/pcb/LDFLAGS /target/libs/script/gpmi/ldflags +# append /local/pcb/LIBS /target/libs/script/gpmi/libs + + append /local/pcb/RULES [@ + +$(PCB_GPMI)/gpmi_plugin/gpmi_buildin.a: FORCE + cd $(PCB_GPMI)/gpmi_plugin && make all_buildin + +@] + + end + case {plugin} + append /local/pcb/all [@ $(PLUGIDIR)/gpmi_plugin.so @] + append /local/pcb/RULES [@ + +mod_pcb_gpmi: $(PLUGIDIR)/gpmi_plugin.so + +$(PLUGIDIR)/gpmi_plugin.so: $(PCB_GPMI)/gpmi_plugin/gpmi_plugin.so + $(MKDIR) $(PLUGIDIR) + $(CP) $(PCB_GPMI)/gpmi_plugin/gpmi_plugin.so $(PLUGIDIR)/gpmi_plugin.so + +@] + + append /local/pcb/CLEANFILES [@ $(PLUGIDIR)/gpmi_plugin.so @] + + append /local/pcb/RULES [@ + +$(PCB_GPMI)/gpmi_plugin/gpmi_plugin.so: FORCE + cd $(PCB_GPMI)/gpmi_plugin && make all_plugin + +@] + end + case {disable} + end +end Index: tags/1.2.7/src_plugins/gpmi/gpmi.pup =================================================================== --- tags/1.2.7/src_plugins/gpmi/gpmi.pup (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/gpmi.pup (revision 13657) @@ -0,0 +1,7 @@ +$class feature +$short GPMI scripting +$long Scriptable plugin system with about 10 scripting languages supported and dynamic load/unload of scripts that can manipulate the GUI, the board, can implement exporters, etc. +$state works +$ldefault: if gpmi is installed +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile (revision 13657) @@ -0,0 +1,28 @@ +PCB_GPMI_ROOT=. + +all: + cd gpmi_plugin; $(MAKE) all + +include ../../../Makefile.conf +PLUGIN_DIR=$(LIBDIR)/plugins + +clean: + cd gpmi_plugin; $(MAKE) clean + +test: all + cd host_lib; ./test.sh + + +# TODO: temporary code until gpmi-config is fixed to generate install rules +install: + -mkdir -p $(PLUGIN_DIR)/pcb-rnd-gpmi/ + if test -f gpmi_plugin/gpmi_plugin.so; then cp gpmi_plugin/gpmi_plugin.so $(PLUGIN_DIR)/gpmi_plugin.so; fi + cp `ls gpmi_plugin/gpmi_pkg/*.h gpmi_plugin/gpmi_pkg/*.so` $(PLUGIN_DIR)/pcb-rnd-gpmi/ + +linstall: + -mkdir -p $(PLUGIN_DIR)/pcb-rnd-gpmi/ + -if test -f gpmi_plugin/gpmi_plugin.so; then ln -sf "`pwd`/gpmi_plugin/gpmi_plugin.so" "$(PLUGIN_DIR)/gpmi_plugin.so"; fi + -for n in `ls gpmi_plugin/gpmi_pkg/*.h gpmi_plugin/gpmi_pkg/*.so`; do ln -sf "`pwd`/$$n" "$(PLUGIN_DIR)/pcb-rnd-gpmi/`basename $$n`"; done + +uninstall: + rm -rf $(PLUGIN_DIR)/pcb-rnd-gpmi Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile.config.in =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile.config.in (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/Makefile.config.in (revision 13657) @@ -0,0 +1,16 @@ +print [@ +### Generated by scconfig, do not edit ### + +###TODO1### +PCB_SRC=$(PCB_GPMI_ROOT)/../../.. + +PCB_CFLAGS= \ + @/local/global_cflags@ \ + @/target/libs/sul/glib/cflags@ \ + @/target/libs/script/gpmi/cflags@ \ + -I$(PCB_SRC)/src_3rd \ + -I$(PCB_SRC)/src_3rd/liblihata + +PCB_LDFLAGS= @/target/libs/script/gpmi/ldflags@ + +@] Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile (revision 13657) @@ -0,0 +1,37 @@ +PCB_GPMI_ROOT=.. +include Makefile.gpmi +include $(PCB_GPMI_ROOT)/Makefile.config + +CFLAGS += -Wall -g -I$(PCB_SRC) $(PCB_CFLAGS) + +COMMON_OBJS = scripts.o manage_scripts.o +BUILDIN_OBJS = gpmi_buildin.o $(COMMON_OBJS) +PLUGIN_OBJS = gpmi_plugin.o $(COMMON_OBJS) + +all: gpmi_plugin.so gpmi_buildin.a + cd gpmi_pkg; make + +all_plugin: gpmi_plugin.so + cd gpmi_pkg; make + +all_buildin: gpmi_buildin.a + cd gpmi_pkg; make + +gpmi_buildin.a: $(BUILDIN_OBJS) + ar rvu gpmi_buildin.a $(BUILDIN_OBJS) + +gpmi_plugin.so: $(PLUGIN_OBJS) + $(CC) $(LDFLAGS) -shared -rdynamic -o gpmi_plugin.so $(PLUGIN_OBJS) $(PCB_LDFLAGS) + +gpmi_plugin.o: gpmi_plugin.c scripts.h + +gpmi_buildin.o: gpmi_plugin.c scripts.h + $(CC) -DPLUGIN_INIT_NAME=hid_gpmi_init $(CFLAGS) -c gpmi_plugin.c -o gpmi_buildin.o + +scripts.o: scripts.c + +manage_scripts.o: manage_scripts.c + +clean: + rm gpmi_plugin.o gpmi_plugin.so gpmi_buildin.a gpmi_buildin.o $(COMMON_OBJS) 2>/dev/null ; true + cd gpmi_pkg; $(MAKE) clean Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am (revision 13657) @@ -0,0 +1,15 @@ +# This file is package-specific. Do include it in the distribution. +# +# GPMI fingerprint: Makefile.am.ext-pkg + +# End INST_PATH with / +INST_PATH = pcb-gpmi/ +FILE_NAME = actions + +SOURCE = actions.c +HEADER = actions.h + +PKG_LDFLAGS = + +include ../../../Makefile.config +INCLUDES = -I $(PCB_SRC) Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep (revision 13657) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c (revision 13657) @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include "src/global_typedefs.h" +#include "src/hid.h" +#include "src/error.h" +#include "actions.h" +#include "src/hid_actions.h" +#include "src/compat_misc.h" +#include "../../gpmi_plugin.h" + +typedef struct acontext_s acontext_t; + +struct acontext_s { + pcb_hid_action_t action; + char *name; + gpmi_module *module; + acontext_t *next; +}; + +static int action_argc = 0; +static const char **action_argv = NULL; + +const char *action_arg(int argn) +{ + if ((argn < 0) || (argn >= action_argc)) + return NULL; + return action_argv[argn]; +} + + +static int action_cb(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + acontext_t *ctx = (acontext_t *)pcb_current_action; + int action_argc_old; + const char **action_argv_old; + + /* save argc/argv for action_arg() */ + action_argc_old = action_argc; + action_argv_old = action_argv; + action_argc = argc; + action_argv = argv; + + /* call event */ + gpmi_event(ctx->module, ACTE_action, ctx->name, argc, x, y); + + /* restore argc/argv of action_arg() */ + action_argc = action_argc_old; + action_argv = action_argv_old; + + return 0; +} + +static void cleanup_action(gpmi_module *mod, gpmi_cleanup *cl) +{ + acontext_t *ctx = cl->argv[0].p; + pcb_hid_remove_action(&ctx->action); + free((char *)ctx->action.name); + if (ctx->action.need_coord_msg != NULL) + free((char *)ctx->action.need_coord_msg); + free((char *)ctx->action.description); + free((char *)ctx->action.syntax); + free(ctx); +} + +int action_register(const char *name, const char *need_xy, const char *description, const char *syntax) +{ + acontext_t *ctx; + + + if ((need_xy != NULL) && (*need_xy == '\0')) + need_xy = NULL; + + + ctx = malloc(sizeof(acontext_t)); + ctx->action.name = pcb_strdup(name); + ctx->action.need_coord_msg = pcb_strdup_null(need_xy); + ctx->action.description = pcb_strdup(description); + ctx->action.syntax = pcb_strdup(syntax); + ctx->action.trigger_cb = action_cb; + ctx->name = pcb_strdup(name); + ctx->module = gpmi_get_current_module(); + ctx->next = NULL; + + pcb_hid_register_action(&ctx->action, gpmi_cookie, 0); + + gpmi_mod_cleanup_insert(ctx->module, cleanup_action, "p", ctx); + + pcb_trace("action %d registered.\n", name); + return 0; +} + +int action(const char *cmdline) +{ + return pcb_hid_parse_command(cmdline); +} + +void create_menu(const char *path, const char *action, const char *mnemonic, const char *hotkey, const char *tooltip) +{ + pcb_gui->create_menu(path, action, mnemonic, hotkey, tooltip, "TODO#2"); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h (revision 13657) @@ -0,0 +1,56 @@ +#include +#include "src/pcb-printf.h" + +#undef snprintf +#define snprintf pcb_snprintf + +/* Generated when an action registered by the script is executed. + Arguments: + name: name of the action (as registed using function action_register()) + argc: number of arguments. Arguments can be accessed using function action_arg + x, y: optional coords, if need_xy was not empty at action_register */ +gpmi_define_event(ACTE_action)(const char *name, int argc, int x, int y); + +/* Generated right after gui initialization, before the gui main loop. + Arguments: + argc: number of arguments the gui was initialized with. + argv[]: arguments the gui was initialized with - unaccessible for the scripts. */ +gpmi_define_event(ACTE_gui_init)(int argc, char **argv); + + +/* Generated right before unloading a script to give the script a chance + to clean up. + Arguments: + conffile: the name of the config file that originally triggered laoding the script, or empty if the script was loaded from the gui. */ +gpmi_define_event(ACTE_unload)(const char *conffile); + +/* Register an action in PCB - when the action is executed, event + ACTE_action is generated with the action name. + Multiple actions can be registered. Any action registered by the script + will trigger an ACTE_event sent to the script. + Arguments: + name: name of the action + need_xy: the question the user is asked when he needs to choose a coordinate; if empty, no coordinate is asked + description: description of the action (for the help) + syntax: syntax of the action (for the help) + Returns 0 on success. + */ +int action_register(const char *name, const char *need_xy, const char *description, const char *syntax); + +/* extract the (argn)th event argument for the current action (makes sense only in an ACTE_action event handler */ +const char *action_arg(int argn); + +/* call an existing action using PCB syntax (e.g. foo(1, 2, 3)) + Returns non-zero on error; generally returns value of the action + (which is also non-zero on error). */ +int action(const char *cmdline); + +/* Create a new menu or submenu at path. Missing parents are created + automatically with empty action, mnemonic, hotkey and tooltip. + Arguments: + path: the full path of the new menu + action: this action is executed when the user clicks on the menu + mnemonic: which letter to underline in the menu text (will be the fast-jump-there key once the menu is open) + hotkey: when this key is pressed in the main gui, the action is also triggered; the format is modifiers<Key>letter, where modifiers is Alt, Shift or Ctrl. This is the same syntax that is used in the .res files. + tooltip: short help text */ +void create_menu(const char *path, const char *action, const char *mnemonic, const char *hotkey, const char *tooltip); Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c (revision 13657) @@ -0,0 +1,19 @@ +#include + +int PKG_FUNC(init)() +{ + return 0; +} + +void PKG_FUNC(uninit)() { +} + +void PKG_FUNC(register)() { +} + +int PKG_FUNC(checkver)(int requested) { + if (requested <= 1) + return 0; + + return -1; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf (revision 13657) @@ -0,0 +1,18 @@ +@/local/headers + actions.h + +@/local/srcs + actions.c + +@/local/file_name + actions + +@/local/inst_path + actions + +@/local/CFLAGS + -I.. -I$(PCB_SRC) $(PCB_CFLAGS) -D###/target/sys/class### + +@@/local/hook/postall + PCB_GPMI_ROOT=../../.. + include $(PCB_GPMI_ROOT)/Makefile.config Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am (revision 13657) @@ -0,0 +1,17 @@ +# This file is package-specific. Do include it in the distribution. +# +# GPMI fingerprint: Makefile.am.ext-pkg + +# End INST_PATH with / +INST_PATH = pcb-gpmi/ +FILE_NAME = coordgeo + +SOURCE = coordgeo.c +HEADER = coordgeo.h + +PKG_LDFLAGS = -lm + +include ../../../Makefile.config +INCLUDES = -I $(PCB_SRC) + +test: test.o coordgeo.o Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep (revision 13657) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c (revision 13657) @@ -0,0 +1,580 @@ +#include +#include +#include "coordgeo.h" +#include "src/compat_misc.h" + +cg_obj_t *cg_objs = NULL; +int cg_objs_used = 0, cg_objs_alloced = 0; + +#define DEGMPY 10000.0 +#define PI 3.141592654 + +#define OBJ(i) cg_objs[i] +#define OBJ_VALID(i) ((i >= 0) && (i < cg_objs_used)) + +/* todo */ +#define invalid -0xFFFF + +static int oalloc() +{ + int id; + if (cg_objs_used >= cg_objs_alloced) { + cg_objs_alloced = cg_objs_used + 128; + cg_objs = realloc(cg_objs, sizeof(cg_obj_t) * cg_objs_alloced); + } + id = cg_objs_used; + cg_objs_used++; + return id; +} + +static void ofree(int id) +{ + /* todo */ +} + +int cg_new_object(cg_obj_type_t type, int x1, int y1, int x2, int y2, int r) +{ + int id; + + id = oalloc(); + OBJ(id).type = type; + OBJ(id).x1 = x1; + OBJ(id).y1 = y1; + OBJ(id).x2 = x2; + OBJ(id).y2 = y2; + OBJ(id).r = r; + return id; +} + +static inline int cg_clone_object_(cg_obj_t *o) +{ + int id; + + id = oalloc(); + OBJ(id) = *o; + return id; +} + +int cg_clone_object(int objID) +{ + return cg_clone_object_(&OBJ(objID)); +} + +/* destroys an object by ID */ +void cg_destroy_object(int ID) +{ + ofree(ID); +} + +/* -- field accessors -- */ +cg_obj_type_t cg_get_type(int objID) +{ + return OBJ(objID).type; +} + +int cg_get_coord(int objID, cg_coord_t coordname) +{ + switch(coordname) { + case CG_X1: return OBJ(objID).x1; + case CG_Y1: return OBJ(objID).y1; + case CG_X2: return OBJ(objID).x2; + case CG_Y2: return OBJ(objID).y2; + case CG_R: return OBJ(objID).r; + } + return invalid; +} + +void cg_set_coord(int objID, cg_coord_t coordname, int newvalue) +{ + switch(coordname) { + case CG_X1: OBJ(objID).x1 = newvalue; + case CG_Y1: OBJ(objID).y1 = newvalue; + case CG_X2: OBJ(objID).x2 = newvalue; + case CG_Y2: OBJ(objID).y2 = newvalue; + case CG_R: OBJ(objID).r = newvalue; + } +} + + +/* -- object operations -- */ +double cg_dist_(int x1, int y1, int x2, int y2) +{ + int dx, dy; + + dx = x2 - x1; + dy = y2 - y1; + return sqrt(dx * dx + dy * dy); +} + +int cg_solve_quad(double a, double b, double c, double *x1, double *x2) +{ + double d; + + d = b * b - 4 * a * c; + if (d < 0) + return 0; + if (d != 0) + d = sqrt(d); + + if (x1 != NULL) + *x1 = (-b + d) / (2 * a); + + if (x2 != NULL) + *x2 = (-b - d) / (2 * a); + + if (d == 0) + return 1; + return 2; +} + + +/* return ID to a new object which is parallel obj in distance dist + - for a line dist > 0 means a new line right to the original + (looking from x1;y1 towards x2;y2) + - for arc the same rule applies, looking from angle x2 towards y2 + - for circle dist > 0 means smaller concentric circle + - for point and vector always returns invalid +*/ +int cg_para_obj(int objID, int dist) +{ + cg_obj_t v1, v2; + int rid; + + switch(OBJ(objID).type) { + case CG_POINT: + case CG_VECTOR: + return -1; + case CG_ARC: + /* TODO */ + abort(); + break; + case CG_CIRCLE: + rid = cg_clone_object(objID); + OBJ(rid).r -= dist; + return rid; + case CG_LINE: + cg_perp_line_(&OBJ(objID), &v1, OBJ(objID).x1, OBJ(objID).y1, dist); + cg_perp_line_(&OBJ(objID), &v2, OBJ(objID).x2, OBJ(objID).y2, dist); + rid = oalloc(); + OBJ(rid).type = CG_LINE; + OBJ(rid).x1 = v1.x2; + OBJ(rid).y1 = v1.y2; + OBJ(rid).x2 = v2.x2; + OBJ(rid).y2 = v2.y2; + OBJ(rid).r = 0; + return rid; + } + return -1; +} + +void cg_perp_line_(const cg_obj_t *i, cg_obj_t *o, int xp, int yp, int len) +{ + double dx, dy, dl; + + dx = -(i->y2 - i->y1); + dy = +(i->x2 - i->x1); + dl = sqrt(dx * dx + dy * dy); + dx = dx / dl; + dy = dy / dl; + + o->type = CG_LINE; + o->x1 = xp; + o->y1 = yp; + o->x2 = pcb_round((double)xp + dx * (double)len); + o->y2 = pcb_round((double)yp + dy * (double)len); + o->r = 0; +} + + +/* return ID to a new line which is perpendicular to line1 and starts at + point xp;yp and is len long */ +int cg_perp_line(int line1ID, int xp, int yp, int len) +{ + int id; + + id = oalloc(); + cg_perp_line_(&OBJ(line1ID), &OBJ(id), xp, yp, len); + + return id; +} + +int cg_ison_line_(cg_obj_t *l, int x, int y, int extend) +{ + int vx, vy; + + vx = l->x2 - l->x1; + vy = l->y2 - l->y1; + + /* is the point on the extended line? */ + if ((vy * x - vx * y) != (vy * l->x1 - vy * l->y1)) + return 0; + + if ((!extend) && ((x < l->x1) || (x > l->x2))) + return 0; + return 1; +} + +int cg_ison_arc_(cg_obj_t *a, int x, int y, int extend) +{ + double deg; + + /* is the point on the circle? */ + if (cg_dist_(a->x1, a->y1, x, y) != a->r) + return 0; + + /* for circles (or an extended arc, which is just a circle) this means the point must be on */ + if (extend || (a->type == CG_CIRCLE)) + return 1; + + /* check if the point is between start and end angles */ + deg = atan2(y - a->y1, x - a->x1) * DEGMPY; + if ((deg >= a->x2) && (deg >= a->y2)) + return 1; + + return 0; +} + +int cg_ison_point_(cg_obj_t *p, int x, int y) +{ + return (p->x1 == x) && (p->y1 == y); +} + +int cg_ison_(cg_obj_t *o, int x, int y, int extend) +{ + switch(o->type) { + case CG_POINT: return cg_ison_point_(o, x, y); + case CG_VECTOR: return 1; + case CG_LINE: return cg_ison_line_(o, x, y, extend); + case CG_ARC: return cg_ison_arc_(o, x, y, extend); + case CG_CIRCLE: return cg_ison_circle_(o, x, y); + } + + /* can't get here */ + abort(); + return 0; +} + +/* intersection of 2 lines (always returns 1) */ +int cg_intersect_ll(cg_obj_t *l1, cg_obj_t *l2, cg_obj_t *o) +{ + double ua, ub, xi, yi, X1, Y1, X2, Y2, X3, Y3, X4, Y4, tmp; + + /* maths from http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ */ + + X1 = l1->x1; + X2 = l1->x2; + X3 = l2->x1; + X4 = l2->x2; + Y1 = l1->y1; + Y2 = l1->y2; + Y3 = l2->y1; + Y4 = l2->y2; + + tmp = ((Y4-Y3)*(X2-X1) - (X4-X3)*(Y2-Y1)); + 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); + + o->type = CG_LINE; + o->x1 = o->x2 = pcb_round(xi); + o->y1 = o->y2 = pcb_round(yi); + o->r = 0; + return 1; +} + +/* intersections of a line and a circle (returns number of possible intersections) */ +int cg_intersect_lc(cg_obj_t *l, cg_obj_t *c, cg_obj_t *o) +{ + int x1, y1, vx, vy, a, vx2, ints; + double A, B, C, X1, X2, Y1, Y2; + + /* first we transform the line to the coordinate system with origo in the + center of the circle - this will simplify the equations */ + x1 = l->x1 - c->x1; + y1 = l->y1 - c->y1; + vx = l->x2 - l->x1; + vy = l->y2 - l->y1; + + /* some cache */ + a = vy * x1 - vx * y1; + vx2 = vx * vx; + + /* this quadratic equation results in the two intersections, X1 and X2 */ + A = 1+vy*vy/vx2; + B = - 2*a*vy / (vx2); + C = a*a / vx2 - c->r * c->r; + + ints = cg_solve_quad(A, B, C, &X1, &X2); + if (ints == 0) + return 0; + + /* knowing X1 and X2 we can easily get Y1 and Y2 */ + Y1 = (a - vy * X1) / (-vx); + Y2 = (a - vy * X2) / (-vx); + + /* transoform back to the original coordinate system */ + X1 += c->x1; + X2 += c->x1; + Y1 += c->y1; + Y2 += c->y1; + + /* set up return line and return number of intersections */ + o->type = CG_LINE; + o->x1 = X1; + o->y1 = Y1; + o->x2 = X2; + o->y2 = Y2; + o->r = 0; + return ints; +} + +/* intersections of 2 circles (returns number of possible intersections) */ +int cg_intersect_cc(cg_obj_t *c1, cg_obj_t *c2, cg_obj_t *o) +{ + double d, a, h; + int P2x, P2y; + + d = cg_dist_(c1->x1, c1->y1, c2->x1, c2->y1); + + if (d > c1->r + c2->r) + return 0; /* separate */ + if (d < abs(c1->r - c2->r)) + return 0; /* contained */ + if ((d == 0) && (c1->r == c2->r)) + return -1; /* they are the same circle */ + + /* some temps */ + a = (double)(c1->r * c1->r - c2->r * c2->r + d * d) / (2.0 * d); + h = sqrt(c1->r * c1->r - a * a); + P2x = c1->x1 + a * (c2->x1 - c1->x1) / d; + P2y = c1->y1 + a * (c2->y1 - c1->y1) / d; + + /* final coordinates */ + o->type = CG_LINE; + o->x1 = P2x + h * (c2->y1 - c1->y1) / d; + o->y1 = P2y - h * (c2->x1 - c1->x1) / d; + o->x2 = P2x - h * (c2->y1 - c1->y1) / d; + o->y2 = P2y + h * (c2->x1 - c1->x1) / d; + + if (d == c1->r + c2->r) + return 1; + return 2; +} + + +int cg_intersect_(cg_obj_t *i1, cg_obj_t *i2, cg_obj_t *o) +{ + switch(i1->type) { + case CG_VECTOR: + /* invalid */ + return -1; + case CG_POINT: + /* TODO: ison */ + break; + case CG_LINE: + switch(i2->type) { + case CG_VECTOR: + /* invalid */ + return -1; + case CG_POINT: + /* TODO: ison */ + break; + case CG_LINE: + return cg_intersect_ll(i1, i2, o); + case CG_CIRCLE: + case CG_ARC: + return cg_intersect_lc(i1, i2, o); + } + return -1; + case CG_CIRCLE: + case CG_ARC: + switch(i2->type) { + case CG_VECTOR: + /* invalid */ + return -1; + case CG_POINT: + /* TODO: ison */ + break; + case CG_LINE: + return cg_intersect_lc(i2, i1, o); + case CG_CIRCLE: + case CG_ARC: + return cg_intersect_cc(i1, i2, o); + } + return -1; + } + return -1; +} + +int cg_intersect(int obj1ID, int obj2ID, int extend) +{ + cg_obj_t res; + int ints; + + ints = cg_intersect_(&OBJ(obj1ID), &OBJ(obj2ID), &res); + + /* if we needed to extend, we shouldn't care if the intersections + are on the objects. */ + if (extend) + return cg_clone_object_(&res); + + + while(1) { + if (ints == 0) + return -1; + + if ((!cg_ison_(&OBJ(obj1ID), res.x1, res.y1, 0)) || (!cg_ison_(&OBJ(obj2ID), res.x1, res.y1, 0))) { + /* x1;y1 is not on the objects. make x2;y2 the new x1;y1 and test again */ + res.x1 = res.x2; + res.y1 = res.y2; + ints--; + } + else + break; + } + + /* x1;y1 is on the objects; check x2;y2 if we still have 2 intersections */ + if ((ints == 2) && ((!cg_ison_(&OBJ(obj1ID), res.x2, res.y2, 0)) || (!cg_ison_(&OBJ(obj2ID), res.x2, res.y2, 0)))) { + /* x2;y2 not on the objects, kill it */ + res.x2 = res.x1; + res.y2 = res.y1; + ints = 1; + } + + return cg_clone_object_(&res); +} + +/* Truncate an object at x;y. Point x;y must be on the object. Optionally + invert which part is kept. Default: + - line: keep the part that originates from x1;y1 + - arc: keep the segment that is closer to the starting angle (x2) + - circle: always fails + - point: always fails + - vector: always fails + Returns 0 on success. +*/ +int cg_truncate_(cg_obj_t *o, int x, int y, int invert_kept) +{ + double a; + + /* point is not on the object */ + if (!cg_ison_(o, x, y, 0)) + return 1; + + switch(o->type) { + case CG_VECTOR: + case CG_POINT: + case CG_CIRCLE: + return 2; + case CG_LINE: + if (!invert_kept) { + o->x2 = x; + o->y2 = y; + } + else { + o->x1 = x; + o->y1 = y; + } + break; + case CG_ARC: + a = atan2(y - o->y1, x - o->x1) * DEGMPY; + if (!invert_kept) + o->y2 = a; + else + o->x2 = a; + break; + } + return 0; +} + +int cg_truncate(int objID, int x, int y, int invert_kept) +{ + return cg_truncate_(&OBJ(objID), x, y, invert_kept); +} + +/* cut target object with cutting edge object; optionally invert which + part is kept of target. Default: + - when line cuts, looking from x1;y1 towards x2;y2, right is kept + - when circle or arc cuts, we are "walking" clock-wise, right is kept + (in short, inner part is kept) + Returns 0 on success. +*/ +int cg_cut_(cg_obj_t *t, cg_obj_t *c, int invert_kept) +{ + cg_obj_t intersects; + int num_intersects, ni; + + num_intersects = cg_intersect_(t, c, &intersects); + if (num_intersects < 1) + return 1; + + for(; num_intersects > 0; num_intersects--) + { + switch(c->type) { + case CG_POINT: + case CG_VECTOR: + return 1; + case CG_LINE: + /* TODO: leftof */ + return 1; + case CG_CIRCLE: + case CG_ARC: + /* TODO: leftof */ + break; + } + /* shift intersection */ + intersects.x1 = intersects.x2; + intersects.y1 = intersects.y2; + } + return 0; +} + +int cg_cut(int targetID, int cutting_edgeID, int invert_kept); + +cg_obj_t *cg_get_object(int ID) +{ + if (OBJ_VALID(ID)) + return &OBJ(ID); + else + return NULL; +} + +int cg_simplify_object_(cg_obj_t *o) +{ + int ret = 0; /* no direct returns because CG_ARC can have more than one optimization */ + switch(o->type) { + case CG_LINE: + if ((o->x1 == o->x2) && (o->y1 == o->y2)) { + o->type = CG_POINT; + ret++; + break; + } + break; + case CG_ARC: + if ((fabs(o->x2 - o->y2) * DEGMPY) >= 2*PI) { + o->type = CG_CIRCLE; + ret++; + } + /* intended fall trough for r==0 check */ + case CG_CIRCLE: + if (o->r == 0) { + o->type = CG_POINT; + ret++; + break; + } + break; + default: + /* no simplification possible */ + ; + } + return ret; +} + + +int cg_simplify_object(int ID) +{ + if (OBJ_VALID(ID)) + return cg_simplify_object_(&OBJ(ID)); + return -1; +} \ No newline at end of file Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h (revision 13657) @@ -0,0 +1,127 @@ +#include +#include "src/pcb-printf.h" + +#undef snprintf +#define snprintf pcb_snprintf + +typedef enum cg_obj_type_e { + CG_POINT, /* x1;y1 */ + CG_LINE, /* from x1;y1 to x2;y2 */ + CG_VECTOR, /* x1;y1 (not associated with a point) */ + CG_CIRCLE, /* center x1;y1, radius r */ + CG_ARC /* center x1;y1, radius r, from x2 rad to y2 rad */ +} cg_obj_type_t; + +typedef enum cg_coord_e { + CG_X1, + CG_Y1, + CG_X2, + CG_Y2, + CG_R +} cg_coord_t; + + +/* -- object administration -- */ +/* returns ID to the new object */ +int cg_new_object(cg_obj_type_t type, int x1, int y1, int x2, int y2, int r); + +/* cloned an existing object and returns ID to the new object */ +int cg_clone_object(int objID); + +/* destroys an object by ID */ +void cg_destroy_object(int ID); + +/* -- field accessors -- */ +cg_obj_type_t cg_get_type(int objID); +int cg_get_coord(int objID, cg_coord_t coordname); +void cg_set_coord(int objID, cg_coord_t coordname, int newvalue); + + +/* -- object operations -- */ +/* return ID to a new object which is parallel obj in distance dist + - for a line dist > 0 means a new line right to the original + (looking from x1;y1 towards x2;y2) + - for arc the same rule applies, looking from angle x2 towards y2 + - for circle dist > 0 means smaller concentric circle + - for point and vector always returns invalid +*/ +int cg_para_obj(int objID, int dist); + +/* return ID to a new line which is perpendicular to line1 and starts at + point xp;yp and is len long */ +int cg_perp_line(int line1ID, int xp, int yp, int len); + +/* returns ID to a line which marks the intersection(s) of two objects or + returns -1 if there's no intersection. If there's only one intersection, + the start and end point of the line is the same point. With the current + primitives, there can not be more than 2 intersections between 2 objects, + except when they have infinite amount of intersections: + - overlapping lines + - overlapping arcs + - two circles with the same radius and center + If extend is non-zero, the objects are extended during the calculation. + For lines this means infinite length, for arcs this means handling them as + circles. +*/ +int cg_intersect(int obj1ID, int obj2ID, int extend); + +/* Truncate an object at x;y. Point x;y must be on the object. Optionally + invert which part is kept. Default: + - line: keep the part that originates from x1;y1 + - arc: keep the segment that is closer to the starting angle (x2) + - circle: always fails + - point: always fails + - vector: always fails + Returns 0 on success. +*/ +int cg_truncate(int objID, int x, int y, int invert_kept); + +/* cut target object with cutting edge object; optionally invert which + part is kept of target. Defaults: + - when line cuts, looking from x1;y1 towards x2;y2, right is kept + - when circle or arc cuts, we are "walking" clock-wise, right is kept + (in short, inner part is kept) + - vector and point fails + Returns 0 on success. +*/ +int cg_cut(int targetID, int cutting_edgeID, int invert_kept); + +/* Convert object to simpler form, if possible: + - if x1;y1 and x2;y2 are equal in a line, it is converted to a point + - if radius of a circle or arc is zero, it is converted to a point + - if an arc is a full circle, convert it to a circle + Returns number of simplifications (0, 1 or 2) issued or -1 for + invalid object ID. +*/ +int cg_simplify_object(int ID); + + +/* these are for C API, scripts have no direct access */ +typedef struct cg_obj_s { + cg_obj_type_t type; + int x1, y1, x2, y2; + int r; +} cg_obj_t; + +extern cg_obj_t *cg_objs; +extern int cg_objs_used, cg_objs_alloced; + +nowrap cg_obj_t *cg_get_object(int ID); + +/* create a line in o that is perpendicular to i and starts at point xp and yp */ +nowrap void cg_perp_line_(const cg_obj_t *i, cg_obj_t *o, int xp, int yp, int len); + +/* distance */ +nowrap double cg_dist_(int x1, int y1, int x2, int y2); + +/* is point on the object? Extend means the object is extended (lines become + infinite long, arcs become circles). pcb_vector_t always returns 1. */ +nowrap int cg_ison_(cg_obj_t *o, int x, int y, int extend); +nowrap int cg_ison_line_(cg_obj_t *l, int x, int y, int extend); +nowrap int cg_ison_arc_(cg_obj_t *a, int x, int y, int extend); +nowrap int cg_ison_point_(cg_obj_t *p, int x, int y); +#define cg_ison_circle_(c, x, y) cg_ison_arc_(c, x, y, 1) + +/* these calls are the low level versions of the ones defined for scripts above */ +nowrap int cg_simplify_object_(cg_obj_t *o); + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c (revision 13657) @@ -0,0 +1,19 @@ +#include + +int PKG_FUNC(init)() +{ + return 0; +} + +void PKG_FUNC(uninit)() { +} + +void PKG_FUNC(register)() { +} + +int PKG_FUNC(checkver)(int requested) { + if (requested <= 1) + return 0; + + return -1; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf (revision 13657) @@ -0,0 +1,18 @@ +@/local/headers + coordgeo.h + +@/local/srcs + coordgeo.c + +@/local/file_name + coordgeo + +@/local/inst_path + coordgeo + +@/local/CFLAGS + -I$(PCB_SRC) $(PCB_CFLAGS) -D###/target/sys/class### + +@@/local/hook/postall + PCB_GPMI_ROOT=../../.. + include $(PCB_GPMI_ROOT)/Makefile.config Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c (revision 13657) @@ -0,0 +1,199 @@ +#include +#include +#include +#include "coordgeo.h" + +#define POINT_MARK_SIZE 2 +#define PS_SCALE 3 +#define PS_MARGIN 8 + +#define SCALE(v) ((v+PS_MARGIN) * PS_SCALE) + +void line(FILE *ps, int x1, int y1, int x2, int y2) +{ + fprintf(ps, "%d %d moveto\n", SCALE(x1), SCALE(y1)); + fprintf(ps, "%d %d lineto\n", SCALE(x2), SCALE(y2)); +} + +void color(FILE *ps, float r, float g, float b) +{ + static int colorspace=0; + + if (colorspace == 0) { + fprintf(ps, "/DeviceRGB setcolorspace\n"); + colorspace = 1; + } + fprintf(ps, "%f %f %f setcolor\n", r, g, b); +} + + +FILE *ps_start(const char *fn) +{ + FILE *f; + + f = fopen(fn, "w"); + if (f == NULL) + return NULL; + + fprintf(f, "%%!\n"); + + return f; +} + +int ps_draw(FILE *ps, int ID) +{ + cg_obj_t *o; + o = cg_get_object(ID); + assert(o != NULL); + fprintf(ps, "newpath\n"); + + switch(o->type) { + case CG_POINT: + fprintf(ps, "0.1 setlinewidth\n"); + line(ps, o->x1-POINT_MARK_SIZE, o->y1, o->x1+POINT_MARK_SIZE, o->y1); + line(ps, o->x1, o->y1-POINT_MARK_SIZE, o->x1, o->y1+POINT_MARK_SIZE); + break; + case CG_LINE: + fprintf(ps, "0.1 setlinewidth\n"); + line(ps, o->x1, o->y1, o->x2, o->y2); + break; + case CG_VECTOR: + fprintf(ps, "0.1 setlinewidth\n"); + line(ps, o->x1, o->y1, o->x2, o->y2); + break; + case CG_CIRCLE: + fprintf(ps, "0.1 setlinewidth\n"); + fprintf(ps, "%d %d %d %d %d arc\n", SCALE(o->x1), SCALE(o->y1), o->r*PS_SCALE, 0, 360); + break; + case CG_ARC: + fprintf(ps, "0.1 setlinewidth\n"); + fprintf(ps, "%d %d %d %d %d arc\n", SCALE(o->x1), SCALE(o->y1), o->r*PS_SCALE, o->x2, o->y2); + break; + } + + fprintf(ps, "stroke\n"); + return ID; +} + +void ps_end(FILE *ps) +{ + fprintf(ps, "showpage\n"); + fclose(ps); +} + +void test_primitives() +{ + FILE *ps; + + ps = ps_start("primitives.ps"); + cg_destroy_object(ps_draw(ps, cg_new_object(CG_LINE, 0, 0, 10, 10, 0))); + cg_destroy_object(ps_draw(ps, cg_new_object(CG_VECTOR, 20, 0, 30, 10, 0))); + cg_destroy_object(ps_draw(ps, cg_new_object(CG_POINT, 40, 5, 0, 0, 0))); + cg_destroy_object(ps_draw(ps, cg_new_object(CG_CIRCLE, 70, 10, 0, 0, 5))); + cg_destroy_object(ps_draw(ps, cg_new_object(CG_ARC, 90, 10, 0, 45, 5))); + ps_end(ps); +} + +void test_parallels() +{ + FILE *ps; + int obj; + + ps = ps_start("parallels.ps"); + + obj = ps_draw(ps, cg_new_object(CG_LINE, 0, 0, 10, 10, 0)); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, 4))); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, -4))); + cg_destroy_object(obj); + + obj = ps_draw(ps, cg_new_object(CG_CIRCLE, 70, 10, 0, 0, 5)); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, 4))); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, -4))); + cg_destroy_object(obj); + +/* obj = ps_draw(ps, cg_new_object(CG_ARC, 90, 10, 0, 45, 5)); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, 4))); + cg_destroy_object(ps_draw(ps, cg_para_obj(obj, -4))); + cg_destroy_object(obj);*/ + + + ps_end(ps); + +} + +void test_perps() +{ + FILE *ps; + int obj; + + ps = ps_start("perpendicular.ps"); + + obj = ps_draw(ps, cg_new_object(CG_LINE, 0, 0, 10, 10, 0)); + cg_destroy_object(ps_draw(ps, cg_perp_line(obj, 0,0,4))); + cg_destroy_object(ps_draw(ps, cg_perp_line(obj, 10,10,-4))); + cg_destroy_object(obj); + + ps_end(ps); + +} + +void test_intersect() +{ + FILE *ps; + int o1, o2, i; + cg_obj_t *oi; + + ps = ps_start("intersect.ps"); + + /* two lines, intersecting */ + color(ps, 0, 0, 0); + o1 = ps_draw(ps, cg_new_object(CG_LINE, 0, 0, 10, 10, 0)); + o2 = ps_draw(ps, cg_new_object(CG_LINE, 5, 0, 6, 13, 0)); + color(ps, 1, 0, 0); + cg_simplify_object(i = cg_intersect(o1, o2, 1)); + cg_destroy_object(ps_draw(ps, i)); + cg_destroy_object(o1); + cg_destroy_object(o2); + + /* two lines, no visible intersection */ + color(ps, 0, 0, 0); + o1 = ps_draw(ps, cg_new_object(CG_LINE, 20, 0, 30, 10, 0)); + o2 = ps_draw(ps, cg_new_object(CG_LINE, 25, 0, 32, 13, 0)); + color(ps, 1, 0, 0); + cg_simplify_object(i = cg_intersect(o1, o2, 1)); + cg_destroy_object(ps_draw(ps, i)); + cg_destroy_object(o1); + cg_destroy_object(o2); + + /* circle vs. line */ + color(ps, 0, 0, 0); + o1 = ps_draw(ps, cg_new_object(CG_LINE, 40, 0, 55, 15, 0)); + o2 = ps_draw(ps, cg_new_object(CG_CIRCLE, 45, 8, 0, 0, 6)); + color(ps, 1, 0, 0); + cg_simplify_object(i = cg_intersect(o1, o2, 1)); + cg_destroy_object(ps_draw(ps, i)); + cg_destroy_object(o1); + cg_destroy_object(o2); + + /* circle vs. circle */ + color(ps, 0, 0, 0); + o1 = ps_draw(ps, cg_new_object(CG_CIRCLE, 69, 6, 0, 0, 4)); + o2 = ps_draw(ps, cg_new_object(CG_CIRCLE, 65, 8, 0, 0, 6)); + color(ps, 1, 0, 0); + cg_simplify_object(i = cg_intersect(o1, o2, 1)); + cg_destroy_object(ps_draw(ps, i)); + cg_destroy_object(o1); + cg_destroy_object(o2); + + + ps_end(ps); +} + + +int main() +{ + test_primitives(); + test_parallels(); + test_perps(); + test_intersect(); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am (revision 13657) @@ -0,0 +1,16 @@ +# This file is package-specific. Do include it in the distribution. +# +# GPMI fingerprint: Makefile.am.ext-pkg + +# End INST_PATH with / +INST_PATH = pcb-gpmi/ +FILE_NAME = dialogs + +SOURCE = dialogs.c +HEADER = dialogs.h + +PKG_LDFLAGS = + +PCB_GPMI_ROOT=../../.. +include $(PCB_GPMI_ROOT)/Makefile.config +INCLUDES = -I.. -I../.. -I $(PCB_SRC) Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep (revision 13657) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c (revision 13657) @@ -0,0 +1,91 @@ +#include "src/hid_attrib.h" +#include "src/error.h" +#include "dialogs.h" + +extern pcb_hid_t *pcb_gui; + +void dialog_log(const char *msg) +{ + if (pcb_gui == NULL) + fprintf(stderr, "couldn't find gui for log: \"%s\"\n", msg); + else + pcb_message(PCB_MSG_INFO, "%s", msg); +} + +#define empty(s) (((s) == NULL) || ((*s) == '\0')) +int dialog_confirm(const char *msg, const char *ok, const char *cancel) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "couldn't find gui for dialog_confirm: \"%s\"\n", msg); + return -1; + } + + if (empty(ok)) + ok = NULL; + if (empty(cancel)) + cancel = NULL; + + return pcb_gui->confirm_dialog(msg, cancel, ok, NULL); +} +#undef empty + +void dialog_report(const char *title, const char *msg) +{ + if (pcb_gui == NULL) + fprintf(stderr, "couldn't find gui for dialog_report: \"%s\" \"%s\"\n", title, msg); + else + pcb_gui->report_dialog(title, msg); +} + +dynamic char *dialog_prompt(const char *msg, const char *default_) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "couldn't find gui for dialog_prompt: \"%s\" \"%s\"\n", msg, default_); + return NULL; + } + else + return pcb_gui->prompt_for(msg, default_); +} + +dynamic char *dialog_fileselect(const char *title, const char *descr, char *default_file, char *default_ext, const char *history_tag, multiple dialog_fileselect_t flags) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "couldn't find gui for dialog_fileselect\n"); + return NULL; + } + else + return pcb_gui->fileselect(title, descr, default_file, default_ext, history_tag, flags); +} + +void dialog_beep(void) +{ + if (pcb_gui == NULL) + fprintf(stderr, "couldn't find gui for dialog_beep\n"); + else + pcb_gui->beep(); +} + +int dialog_progress(int so_far, int total, const char *message) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "couldn't find gui for dialog_process: %d/%d \"%s\"\n", so_far, total, message); + return -1; + } + return pcb_gui->progress(so_far, total, message); +} + +int dialog_attribute(gpmi_hid_t *hid, const char *title, const char *descr) +{ + if (pcb_gui == NULL) { + fprintf(stderr, "couldn't find gui for dialog_attribute: \"%s\" \"%s\"\n", title, descr); + return -1; + } + + if (hid->result != NULL) { + /* TODO: free string fields to avoid memleaks */ + } + else + hid->result = calloc(sizeof(pcb_hid_attribute_t), hid->attr_num); + + return pcb_gui->attribute_dialog(hid->attr, hid->attr_num, hid->result, title, descr, NULL); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h (revision 13657) @@ -0,0 +1,79 @@ +#include +#include "src/hid.h" +#include "src/global_typedefs.h" +#define FROM_PKG +#include "hid/hid.h" +#include "src/pcb-printf.h" + +#undef snprintf +#define snprintf pcb_snprintf + +/* Filter on what files a file select dialog should list */ +typedef enum dialog_fileselect_e { + FS_NONE = 0, /* none of the below */ + FS_READ = 1, /* when the selected file will be read, not written (HID_FILESELECT_READ) */ + FS_NOT_EXIST = 2, /* the function calling hid->fileselect will deal with the case when the selected file already exists. If not given, then the gui will prompt with an "overwrite?" prompt. Only used when writing. (HID_FILESELECT_MAY_NOT_EXIST) */ + FS_TEMPLATE = 4 /* the call is supposed to return a file template (for gerber output for example) instead of an actual file. Only used when writing. (HID_FILESELECT_IS_TEMPLATE) */ +} dialog_fileselect_t; +gpmi_keyword *kw_dialog_fileselect_e; /* of dialog_fileselect_t */ + +/* Append a msg to the log (log window and/or stderr). */ +void dialog_log(const char *msg); + +/* Ask the user for confirmation (usually using a popup). Returns 0 for + cancel and 1 for ok. + Arguments: + msg: message to the user + ok: label of the OK button + cancel: label of the cancel button + Arguments "ok" and "cancel" may be empty (or NULL) in which + case the GUI will use the default (perhaps localized) labels for + those buttons. */ +int dialog_confirm(const char *msg, const char *ok, const char *cancel); + + +/* Pop up a report dialog. + Arguments: + title: title of the window + msg: message */ +void dialog_report(const char *title, const char *msg); + +/* Ask the user to input a string (usually in a popup). + Arguments: + msg: message or question text + default_: default answer (this may be filled in on start) + Returns the answer. */ +dynamic char *dialog_prompt(const char *msg, const char *default_); + +/* Pops up a file selection dialog. + Arguments: + title: window title + descr: description + default_file_ + default_ext: default file name extension + history_tag + flags: one or more flags (see below) + Returns the selected file or NULL (empty). */ +dynamic char *dialog_fileselect(const char *title, const char *descr, char *default_file_, char *default_ext, const char *history_tag, multiple dialog_fileselect_t flags); + +/* Audible beep */ +void dialog_beep(void); + +/* Request the GUI hid to draw a progress bar. + Arguments: + int so_far: achieved state + int total: maximum state + const char *message: informs the users what they are waiting for + If so_far is bigger than total, the progress bar is closed. + Returns nonzero if the user wishes to cancel the operation. +*/ +int dialog_progress(int so_far, int total, const char *message); + + +/* Pop up an attribute dialog; content (widgets) of the dialog box are coming + from hid (see the hid package). + Arguments: + hid: widgets + title: title of the window + descr: descripting printed in the dialog */ +int dialog_attribute(gpmi_hid_t *hid, const char *title, const char *descr); Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf (revision 13657) @@ -0,0 +1,18 @@ +@/local/headers + dialogs.h + +@/local/srcs + dialogs.c + +@/local/file_name + dialogs + +@/local/inst_path + dialogs + +@/local/CFLAGS + -I.. -I$(PCB_SRC) $(PCB_CFLAGS) -D###/target/sys/class### + +@@/local/hook/postall + PCB_GPMI_ROOT=../../.. + include $(PCB_GPMI_ROOT)/Makefile.config Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am (revision 13657) @@ -0,0 +1,13 @@ +# GPMI fingerprint: Makefile.am.ext-pkg + +# End INST_PATH with / +INST_PATH = pcb-gpmi/ +FILE_NAME = hid + +SOURCE = hid.c +SOURCE += hid_callbacks.c + +HEADER = hid.h +HEADER += hid_events.h +include ../../../Makefile.config +INCLUDES = -I $(PCB_SRC) Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep (revision 13657) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c (revision 13657) @@ -0,0 +1,19 @@ +#include + +int PKG_FUNC(init)() +{ + return 0; +} + +void PKG_FUNC(uninit)() { +} + +void PKG_FUNC(register)() { +} + +int PKG_FUNC(checkver)(int requested) { + if (requested <= 1) + return 0; + + return -1; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf (revision 13657) @@ -0,0 +1,20 @@ +@/local/headers + hid.h + hid_events.h + +@/local/srcs + hid.c + hid_callbacks.c + +@/local/file_name + hid + +@/local/inst_path + hid + +@/local/CFLAGS + -I.. -I$(PCB_SRC) $(PCB_CFLAGS) -D###/target/sys/class### + +@@/local/hook/postall + PCB_GPMI_ROOT=../../.. + include $(PCB_GPMI_ROOT)/Makefile.config Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c (revision 13657) @@ -0,0 +1,307 @@ +#include +#include +#include +#include +#include +#include "src/global_typedefs.h" +#include "src/error.h" +#include "src/hid.h" +#include "src/hid_nogui.h" +#include "src/pcb-printf.h" +#include "src/hid_attrib.h" +#include "src/hid_init.h" +#include "src/compat_misc.h" + +#define FROM_PKG +#include "hid.h" +#include "hid_callbacks.h" + + +void hid_gpmi_data_set(gpmi_hid_t *h, void *data) +{ + h->hid->user_context = data; +} + +gpmi_hid_t *hid_gpmi_data_get(pcb_hid_t *h) +{ + if (h == NULL) + return NULL; + return (gpmi_hid_t *)h->user_context; +} + +gpmi_hid_t *hid_create(char *hid_name, char *description) +{ + gpmi_hid_t *h; + + h = calloc(sizeof(gpmi_hid_t), 1); + h->hid = calloc(sizeof(pcb_hid_t), 1); + + pcb_hid_nogui_init(h->hid); + + h->module = gpmi_get_current_module(); + + h->hid->name = pcb_strdup(hid_name); + h->hid->description = pcb_strdup(description); + h->hid->exporter = 1; + h->hid->gui = 0; + h->hid->struct_size = sizeof(pcb_hid_t); + + h->hid->get_export_options = gpmi_hid_get_export_options; + h->hid->make_gc = gpmi_hid_make_gc; + h->hid->destroy_gc = gpmi_hid_destroy_gc; + h->hid->do_export = gpmi_hid_do_export; + h->hid->parse_arguments = gpmi_hid_parse_arguments; + h->hid->set_crosshair = gpmi_hid_set_crosshair; + h->hid->set_layer_group = gpmi_hid_set_layer_group; + h->hid->set_color = gpmi_hid_set_color; + h->hid->set_line_cap = gpmi_hid_set_line_cap; + h->hid->set_line_width = gpmi_hid_set_line_width; + h->hid->set_draw_xor = gpmi_hid_set_draw_xor; + h->hid->set_draw_faded = gpmi_hid_set_draw_faded; + h->hid->draw_line = gpmi_hid_draw_line; + h->hid->draw_arc = gpmi_hid_draw_arc; + h->hid->draw_rect = gpmi_hid_draw_rect; + h->hid->fill_circle = gpmi_hid_fill_circle; + h->hid->fill_polygon = gpmi_hid_fill_polygon; + h->hid->fill_pcb_polygon = gpmi_hid_fill_pcb_polygon; + h->hid->fill_rect = gpmi_hid_fill_rect; + h->hid->fill_pcb_pv = gpmi_hid_fill_pcb_pv; + h->hid->fill_pcb_pad = gpmi_hid_fill_pcb_pad; + + h->attr_num = 0; + h->attr = NULL; + h->new_gc = NULL; + + hid_gpmi_data_set(h, h); + return h; +} + +dynamic char *hid_get_attribute(gpmi_hid_t *hid, int attr_id) +{ + const char *res; + char buff[128]; + pcb_hid_attr_val_t *v; + + if ((hid == NULL) || (attr_id < 0) || (attr_id >= hid->attr_num) || (hid->result == NULL)) + return 0; + + res = NULL; + + v = &(hid->result[attr_id]); + switch(hid->type[attr_id]) { + case HIDA_Boolean: + if (v->int_value) + res = "true"; + else + res = "false"; + break; + case HIDA_Integer: + pcb_snprintf(buff, sizeof(buff), "%d", v->int_value); + res = buff; + break; + case HIDA_Real: + pcb_snprintf(buff, sizeof(buff), "%f", v->real_value); + res = buff; + break; + case HIDA_String: + case HIDA_Label: + case HIDA_Path: + res = v->str_value; + break; + case HIDA_Enum: + res = hid->attr[attr_id].enumerations[v->int_value]; +/* printf("res='%s' %d\n", res, v->int_value);*/ + break; + case HIDA_Coord: + pcb_sprintf(buff, "%mI", v->coord_value); + res = buff; + break; + case HIDA_Unit: + { + const pcb_unit_t *u; + double fact; + u = get_unit_by_idx(v->int_value); + if (u == NULL) + fact = 0; + else + fact = pcb_unit_to_factor(u); + pcb_snprintf(buff, sizeof(buff), "%f", fact); + res = buff; +/* fprintf(stderr, "unit idx: %d %p res='%s'\n", v->int_value, (void *)u, res);*/ + } + break; + case HIDA_Mixed: + default: + fprintf(stderr, "error: hid_string2val: can't handle type %d\n", hid->type[attr_id]); + + } + if (res == NULL) + return NULL; + return pcb_strdup(res); +} + + +pcb_hid_attr_val_t hid_string2val(const hid_attr_type_t type, const char *str) +{ + pcb_hid_attr_val_t v; + memset(&v, 0, sizeof(v)); + switch(type) { + case HIDA_Boolean: + if ((pcb_strcasecmp(str, "true") == 0) || (pcb_strcasecmp(str, "yes") == 0) || (pcb_strcasecmp(str, "1") == 0)) + v.int_value = 1; + else + v.int_value = 0; + break; + case HIDA_Integer: + v.int_value = atoi(str); + break; + case HIDA_Coord: + { + char *end; + double val; + val = strtod(str, &end); + while(isspace(*end)) end++; + if (*end != '\0') { + const pcb_unit_t *u; + u = get_unit_struct(end); + if (u == NULL) { + pcb_message(PCB_MSG_ERROR, "Invalid unit for HIDA_Coord in the script: '%s'\n", end); + v.coord_value = 0; + } + else + v.coord_value = pcb_unit_to_coord(u, val); + } + else + v.coord_value = val; + } + break; + case HIDA_Unit: + { + const pcb_unit_t *u; + u = get_unit_struct(str); + if (u != NULL) + v.real_value = pcb_unit_to_factor(u); + else + v.real_value = 0; + } + break; + case HIDA_Real: + v.real_value = atof(str); + break; + case HIDA_String: + case HIDA_Label: + case HIDA_Enum: + case HIDA_Path: + v.str_value = pcb_strdup(str); + break; + case HIDA_Mixed: + default: + fprintf(stderr, "error: hid_string2val: can't handle type %d\n", type); + } + return v; +} + +char **hid_string2enum(const char *str, pcb_hid_attr_val_t *def) +{ + char **e; + const char *s, *last; + int n, len; + + for(n=0, s=str; *s != '\0'; s++) + if (*s == '|') + n++; + e = malloc(sizeof(char *) * (n+2)); + + def->int_value = 0; + def->str_value = NULL; + def->real_value = 0.0; + + for(n = 0, last=s=str;; s++) { + + if ((*s == '|') || (*s == '\0')) { + if (*last == '*') { + def->int_value = n; + last++; + } + len = s - last; + e[n] = malloc(len+1); + if (len != 0) + strncpy(e[n], last, len); + e[n][len] = '\0'; + last = s+1; + n++; + } + if (*s == '\0') + break; + } + e[n] = NULL; + return e; +} + +int hid_add_attribute(gpmi_hid_t *hid, char *attr_name, char *help, hid_attr_type_t type, int min, int max, char *default_val) +{ + int current = hid->attr_num; + + /* TODO: should realloc more space here */ + hid->attr_num++; + hid->attr = realloc(hid->attr, sizeof(pcb_hid_attribute_t) * hid->attr_num); + hid->type = realloc(hid->type, sizeof(hid_attr_type_t) * hid->attr_num); + + hid->attr[current].name = pcb_strdup(attr_name); + hid->attr[current].help_text = pcb_strdup(help); + hid->attr[current].type = type; + hid->attr[current].min_val = min; + hid->attr[current].max_val = max; + if (type == HIDA_Unit) { + const pcb_unit_t *u, *all; + all = get_unit_list(); + u = get_unit_struct(default_val); + if (u != NULL) + hid->attr[current].default_val.int_value = u-all; + else + hid->attr[current].default_val.int_value = -1; + } + else if (type == HIDA_Enum) { + hid->attr[current].enumerations = (const char **)hid_string2enum(default_val, &(hid->attr[current].default_val)); + } + else { + hid->attr[current].default_val = hid_string2val(type, default_val); + hid->attr[current].enumerations = NULL; + } + + hid->type[current] = type; + + return current; +} + +static void cleanup_hid_reg(gpmi_module *mod, gpmi_cleanup *cl) +{ + gpmi_hid_t *hid = cl->argv[0].p; + int n; + + pcb_hid_remove_hid(hid->hid); + + for(n = 0; n < hid->attr_num; n++) { + free((char *)hid->attr[n].name); + free((char *)hid->attr[n].help_text); + } + + if (hid->attr != NULL) + free(hid->attr); + if (hid->type != NULL) + free(hid->type); + + free((char *)hid->hid->name); + free((char *)hid->hid->description); + free(hid->hid); + free(hid); +} + +int hid_register(gpmi_hid_t *hid) +{ + pcb_hid_register_hid(hid->hid); + + gpmi_mod_cleanup_insert(NULL, cleanup_hid_reg, "p", hid); + + return 0; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h (revision 13657) @@ -0,0 +1,90 @@ +#include +#include "src/pcb-printf.h" + +#undef snprintf +#define snprintf pcb_snprintf + +/* Type of an HID attribute (usually a widget on an attribute dialog box) */ +typedef enum hid_attr_type_e { + HIDA_Label, /* non-editable label displayed on the GUI */ + HIDA_Integer, /* a sugned integer value */ + HIDA_Real, /* a floating point value */ + HIDA_String, /* one line textual input */ + HIDA_Boolean, /* true/false boolean value */ + HIDA_Enum, /* select an item of a predefined list */ + HIDA_Mixed, /* TODO */ + HIDA_Path, /* path to a file or directory */ + HIDA_Unit, /* select a dimension unit */ + HIDA_Coord /* enter a coordinate */ +} hid_attr_type_t; + +gpmi_keyword *kw_hid_attr_type_e; /* of hid_attr_type_t */ + +/* TODO: these should not be here; GPMI needs to switch over to c99tree! */ +#ifndef FROM_PKG +typedef void pcb_hid_t; +typedef void pcb_hid_attribute_t; +typedef void* pcb_hid_gc_t; +typedef char* pcb_hid_attr_val_t; + +/* Line or arc ending style */ +typedef enum pcb_cap_style_t_e { + Trace_Cap, /* filled circle (trace drawing) */ + Square_Cap, /* rectangular lines (square pad) */ + Round_Cap, /* round pins or round-ended pads, thermals */ + Beveled_Cap /* octagon pins or bevel-cornered pads */ +} pcb_cap_style_t; + +typedef void *pcb_poly_t; +typedef void *pcb_box_t; +#endif + +typedef struct gpmi_hid_s { + gpmi_module *module; + int attr_num; + pcb_hid_attribute_t *attr; + hid_attr_type_t *type; + pcb_hid_t *hid; + pcb_hid_attr_val_t *result; + pcb_hid_gc_t new_gc; +} gpmi_hid_t; + +/* Creates a new hid context. Name and description matters only if the hid is +registered as an pcb_exporter later. */ +gpmi_hid_t *hid_create(char *hid_name, char *description); + +/* Append an attribute in a hid previously created using hid_create(). + Arguments: + hid: hid_t previously created using hid_create() + attr_name: name of the attribute + help: help text for the attribute + type: type of the attribute (input widget type) + min: minimum value of the attribute, if type is integer or real) + max: maximum value of the attribute, if type is integer or real) + default_val: default value of the attribute + Returns an unique ID of the attribute the caller should store for + later reference. For example this ID is used when retrieving the + value of the attribute after the user finished entering data in + the dialog. */ +int hid_add_attribute(gpmi_hid_t *hid, char *attr_name, char *help, hid_attr_type_t type, int min, int max, char *default_val); + +/* Query an attribute from the hid after dialog_attributes() returned. + Arguments: + hid: hid_t previously created using hid_create() + attr_id: the unique ID of the attribute (returned by hid_add_attribute()) + Returns the value (converted to string) set by the user. */ +dynamic char *hid_get_attribute(gpmi_hid_t *hid, int attr_id); + +/* Register the hid; call it after a hid is created and its attributes + are all set up */ +int hid_register(gpmi_hid_t *hid); + +/* For internal use */ +void hid_gpmi_data_set(gpmi_hid_t *h, void *data); + +/* For internal use */ +gpmi_hid_t *hid_gpmi_data_get(pcb_hid_t *h); + +/* For internal use */ +nowrap pcb_hid_attr_val_t hid_string2val(const hid_attr_type_t type, const char *str); + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c (revision 13657) @@ -0,0 +1,178 @@ +#include +#include "src/board.h" +#include "src/global_typedefs.h" +#include "src/hid.h" +#include "src/data.h" +#define FROM_PKG +#include "hid.h" +#include "hid_events.h" +#include "hid_callbacks.h" +#include "src/hid_flags.h" +#include "src/hid_init.h" + +pcb_hid_attribute_t *gpmi_hid_get_export_options(int *num) +{ + gpmi_hid_t *h; + + h = hid_gpmi_data_get(pcb_exporter); + + if (h == NULL) + return NULL; + + gpmi_event(h->module, HIDE_get_export_options, h); + + if (num != NULL) + *num = h->attr_num; + return h->attr; +} + +static char *gcs = "abcdefghijklmnopqrstuvxyz"; +pcb_hid_gc_t gpmi_hid_make_gc(void) +{ + pcb_hid_gc_t ret; + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + + /* TODO: fix gc handling... */ + h->new_gc = (void *)(gcs++); + gpmi_event(h->module, HIDE_make_gc, h, h->new_gc); + ret = h->new_gc; + h->new_gc = NULL; + return ret; +} + +void gpmi_hid_destroy_gc(pcb_hid_gc_t gc) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_destroy_gc, h, gc); +} + +void gpmi_hid_do_export(pcb_hid_attr_val_t * options) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + int save_ons[PCB_MAX_LAYER + 2]; + pcb_hid_expose_ctx_t ctx; + + h->result = options; + gpmi_event(h->module, HIDE_do_export_start, h); + + 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; + + pcb_hid_expose_all(h->hid, &ctx); + pcb_hid_restore_layer_ons(save_ons); + gpmi_event(h->module, HIDE_do_export_finish, h); + h->result = NULL; +} + +void gpmi_hid_parse_arguments(int *pcbargc, char ***pcbargv) +{ + /* Do nothing for now */ + pcb_hid_parse_command_line(pcbargc, pcbargv); +} + +void gpmi_hid_set_crosshair(int x, int y, int cursor_action) +{ + /* Do nothing */ +} + +int gpmi_hid_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_layer_group, h, group, layer, flags, is_empty); + return 1; +} + +void gpmi_hid_set_color(pcb_hid_gc_t gc, const char *name) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_color, h, gc, name); +} + +void gpmi_hid_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_line_cap, h, gc, style); +} + +void gpmi_hid_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_line_width, h, gc, width); +} + +void gpmi_hid_set_draw_xor(pcb_hid_gc_t gc, int xor) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_draw_xor, h, gc, xor); +} + +void gpmi_hid_set_draw_faded(pcb_hid_gc_t gc, int faded) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_set_draw_faded, h, gc, faded); +} + +void gpmi_hid_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_draw_line, h, gc, x1, y1, x2, y2); +} + +void gpmi_hid_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) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_draw_arc, h, gc, cx, cy, xradius, yradius, start_angle, delta_angle); +} + +void gpmi_hid_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_draw_rect, h, gc, x1, y1, x2, y2); +} + +void gpmi_hid_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_fill_circle, h, gc, cx, cy, radius); +} + +void gpmi_hid_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + /* TODO: need accessor for these */ + gpmi_event(h->module, HIDE_fill_polygon, h, gc, x, y); +} + +void gpmi_hid_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) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + /* TODO: need accessor for these */ + gpmi_event(h->module, HIDE_fill_polygon_offs, h, gc, x, y, dx, dy); +} + +void gpmi_hid_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box) +{ + /* TODO */ +} + +void gpmi_hid_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_fill_rect, h, gc, x1, y1, x2, y2); +} + +void gpmi_hid_fill_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t *pad, pcb_bool drawHole, pcb_bool mask) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_fill_pcb_pv, h, fg_gc, bg_gc, pad, drawHole, mask); +} + +void gpmi_hid_fill_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_fill_pcb_pad, h, gc, pad, clear, mask); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h (revision 13657) @@ -0,0 +1,22 @@ +pcb_hid_attribute_t *gpmi_hid_get_export_options(int *num); +pcb_hid_gc_t gpmi_hid_make_gc(void); +void gpmi_hid_destroy_gc(pcb_hid_gc_t gc); +void gpmi_hid_do_export(pcb_hid_attr_val_t * options); +void gpmi_hid_parse_arguments(int *pcbargc, char ***pcbargv); +void gpmi_hid_set_crosshair(int x, int y, int cursor_action); +int gpmi_hid_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty); +void gpmi_hid_set_color(pcb_hid_gc_t gc, const char *name); +void gpmi_hid_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style); +void gpmi_hid_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width); +void gpmi_hid_set_draw_xor(pcb_hid_gc_t gc, int xor); +void gpmi_hid_set_draw_faded(pcb_hid_gc_t gc, int faded); +void gpmi_hid_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +void gpmi_hid_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 gpmi_hid_draw_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +void gpmi_hid_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius); +void gpmi_hid_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t *x, pcb_coord_t *y); +void gpmi_hid_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 gpmi_hid_fill_pcb_polygon(pcb_hid_gc_t gc, pcb_poly_t *poly, const pcb_box_t *clip_box); +void gpmi_hid_fill_rect(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +void gpmi_hid_fill_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t *pad, pcb_bool drawHole, pcb_bool mask); +void gpmi_hid_fill_pcb_pad(pcb_hid_gc_t gc, pcb_pad_t * pad, pcb_bool clear, pcb_bool mask); Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h (revision 13657) @@ -0,0 +1,63 @@ +/*********** Exporter events ************/ + +/* Called before get_exporter_options returns the option list to the GUI hid */ +gpmi_define_event(HIDE_get_export_options)(void *hid); + +/* Called before export redraw starts */ +gpmi_define_event(HIDE_do_export_start)(void *hid); + +/* Called after export redraw finihsed */ +gpmi_define_event(HIDE_do_export_finish)(void *hid); + +/* DRAWING */ + +/* PCB callback events for drawing: change layer */ +gpmi_define_event(HIDE_set_layer_group)(void *hid, long int group, long int layer, unsigned int flags, int is_empty); + +/* PCB callback events for drawing: change drawing color */ +gpmi_define_event(HIDE_set_color)(void *hid, void *gc, const char *name); + +/* PCB callback events for drawing: change drawing line cap style*/ +gpmi_define_event(HIDE_set_line_cap)(void *hid, void *gc, pcb_cap_style_t style); + +/* PCB callback events for drawing: change drawing line width */ +gpmi_define_event(HIDE_set_line_width)(void *hid, void *gc, int width); + +/* PCB callback events for drawing: toggle xor drawing method */ +gpmi_define_event(HIDE_set_draw_xor)(void *hid, void *gc, int xor); + +/* PCB callback events for drawing: toggle faded drawing method */ +gpmi_define_event(HIDE_set_draw_faded)(void *hid, void *gc, int faded); + +/* PCB callback events for drawing: draw a line */ +gpmi_define_event(HIDE_draw_line)(void *hid, void *gc, int x1, int y1, int x2, int y2); + +/* PCB callback events for drawing: draw an arc from center cx;cy */ +gpmi_define_event(HIDE_draw_arc)(void *hid, void *gc, int cx, int cy, int xradius, int yradius, double start_angle, double delta_angle); + +/* PCB callback events for drawing: draw a rectangle */ +gpmi_define_event(HIDE_draw_rect)(void *hid, void *gc, int x1, int y1, int x2, int y2); + +/* PCB callback events for drawing: draw a filled circle */ +gpmi_define_event(HIDE_fill_circle)(void *hid, void *gc, int cx, int cy, int radius); + +/* PCB callback events for drawing: draw a filled ploygon */ +gpmi_define_event(HIDE_fill_polygon)(void *hid, void *gc, int n_coords, int *x, int *y); + +/* PCB callback events for drawing: draw a filled polygon with offs*/ +gpmi_define_event(HIDE_fill_polygon_offs)(void *hid, void *gc, int n_coords, int *x, int *y, int dx, int dy); + +/* PCB callback events for drawing: draw a filled rectangle */ +gpmi_define_event(HIDE_fill_rect)(void *hid, void *gc, int x1, int y1, int x2, int y2); + +/* PCB callback events for drawing: create a new graphical context */ +gpmi_define_event(HIDE_make_gc)(void *hid, void *gc); + +/* PCB callback events for drawing: destroy a graphical context */ +gpmi_define_event(HIDE_destroy_gc)(void *hid, void *gc); + +/* PCB callback events for drawing: TODO */ +gpmi_define_event(HIDE_fill_pcb_pv)(void *hid, void *fg_gc, void *bg_gc, void *pad, int drawHole, int mask); + +/* PCB callback events for drawing: TODO */ +gpmi_define_event(HIDE_fill_pcb_pad)(void *hid, void *pad, int clear, int mask); Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am (revision 13657) @@ -0,0 +1,20 @@ +# This file is package-specific. Do include it in the distribution. +# +# GPMI fingerprint: Makefile.am.ext-pkg + +# End INST_PATH with / +INST_PATH = pcb-gpmi/ +FILE_NAME = layout + +SOURCE = search.c +SOURCE += object.c +SOURCE += create.c +SOURCE += layers.c +SOURCE += page.c + +HEADER = layout.h + +PKG_LDFLAGS = + +include ../../../Makefile.config +INCLUDES = -I $(PCB_SRC) Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep (revision 13657) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c (revision 13657) @@ -0,0 +1,21 @@ +#include "layout.h" +#include "src/pcb-printf.h" +#include "src/conf_core.h" + +double mil2pcb_multiplier() +{ + return 10000.0*2.54; +} + +double mm2pcb_multiplier() +{ + return 1000000.0; +} + +const char *current_grid_unit() +{ + const pcb_unit_t *u = conf_core.editor.grid_unit; + if (u == NULL) + return ""; + return u->suffix; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c (revision 13657) @@ -0,0 +1,149 @@ +#include +#include +#include "layout.h" +#include "src/const.h" +#include "src/board.h" +#include "src/undo.h" +#include "src/conf_core.h" +#include "src/layer.h" +#include "src/compat_misc.h" + + +typedef struct flag_tr_s { + int flag; /* flag or thermal */ + int gpmi, pcb; +} flag_tr_t; + +static flag_tr_t flags[] = { +#warning TODO: get these from conf +#if 0 + {1, FL_SHOWNUMBER, PCB_SHOWNUMBERFLAG}, + {1, FL_LOCALREF, PCB_LOCALREFFLAG}, + {1, FL_CHECKPLANS, PCB_CHECKPLANESFLAG}, + {1, FL_SHOWDRC, PCB_SHOWPCB_FLAG_DRC}, + {1, FL_RUBBERBAND, PCB_RUBBERBANDFLAG}, + {1, FL_DESCRIPTION, PCB_DESCRIPTIONFLAG}, + {1, FL_NAMEONPCB, PCB_NAMEONPCBFLAG}, + {1, FL_AUTODRC, PCB_AUTOPCB_FLAG_DRC}, + {1, FL_ALLDIRECTION, PCB_ALLDIRECTIONFLAG}, + {1, FL_SWAPSTARTDIR, PCB_SWAPSTARTDIRFLAG}, + {1, FL_UNIQUENAME, PCB_UNIQUENAMEFLAG}, + {1, FL_CLEARNEW, PCB_CLEARNEWFLAG}, + {1, FL_SNAPPIN, PCB_SNAPPCB_FLAG_PIN}, + {1, FL_SHOWMASK, PCB_SHOWMASKFLAG}, + {1, FL_THINDRAW, PCB_THINDRAWFLAG}, + {1, FL_ORTHOMOVE, PCB_ORTHOMOVEFLAG}, + {1, FL_LIVEROUTE, PCB_LIVEROUTEFLAG}, + {1, FL_THINDRAWPOLY, PCB_THINDRAWPOLYFLAG}, + {1, FL_LOCKNAMES, PCB_LOCKNAMESFLAG}, + {1, FL_ONLYNAMES, PCB_ONLYNAMESFLAG}, + {1, FL_NEWFULLPOLY, PCB_NEWPCB_FLAG_FULLPOLY}, + {1, FL_HIDENAMES, PCB_HIDENAMESFLAG}, +#endif + + {0, FL_THERMALSTYLE1, 1}, + {0, FL_THERMALSTYLE2, 2}, + {0, FL_THERMALSTYLE3, 3}, + {0, FL_THERMALSTYLE4, 4}, + {0, FL_THERMALSTYLE5, 5}, + {0, 0, 0} +}; + +static pcb_flag_t get_flags(int in) +{ + flag_tr_t *f; + static pcb_flag_t out; + + out.f = 0; + memset(out.t, 0, sizeof(out.t)); + for(f = flags; f->gpmi != 0; f++) { + if (in & f->gpmi) { + if (f->flag) + out.f |= f->pcb; + else + memset(out.t, f->pcb, sizeof(out.t)); + } + } + return out; +} + +static void *layout_create_line_(pcb_layer_t *layer, int x1, int y1, int x2, int y2, int thickness, int clearance, multiple layout_flag_t flags) +{ + void *line; + + line = pcb_line_new(layer, x1, y1, x2, y2, thickness, clearance, get_flags(flags)); + if (line != NULL) { + pcb_undo_add_obj_to_create(PCB_TYPE_LINE, layer, line, line); + return line; + } + return NULL; +} + +layout_object_t *layout_create_line(const char *search_id, layer_id_t layer_id, int x1, int y1, int x2, int y2, int thickness, int clearance, multiple layout_flag_t flags) +{ + pcb_layer_t *layer = pcb_get_layer(PCB->Data, layer_id); + void *res; + if (layer == NULL) + return 0; + res = layout_create_line_(layer, x1, y1, x2, y2, thickness, clearance, flags); + return search_persist_created(search_id, layer_id, res, OM_LINE); +} + +static void *layout_create_via_(int x, int y, int thickness, int clearance, int mask, int hole, const char *name, multiple layout_flag_t flags) +{ + void *pin; + + pin = pcb_via_new(PCB->Data, x, y, thickness, clearance, mask, hole, name, get_flags(flags)); + + if (pin != NULL) { + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, pin, pin, pin); + return pin; + } + return NULL; +} + +layout_object_t *layout_create_via(const char *search_id, int x, int y, int thickness, int clearance, int mask, int hole, const char *name, multiple layout_flag_t flags) +{ + void *res = layout_create_via_(x, y, thickness, clearance, mask, hole, name, flags); + return search_persist_created(search_id, -1, res, OM_VIA); +} + +static void *layout_create_arc_(pcb_layer_t *layer, int x, int y, int width, int height, int sa, int dir, int thickness, int clearance, multiple layout_flag_t flags) +{ + void *arc; + arc = pcb_arc_new(layer, x, y, width, height, sa, dir, thickness, clearance, get_flags(flags)); + if (arc != NULL) { + pcb_undo_add_obj_to_create(PCB_TYPE_ARC, layer, arc, arc); + return 0; + } + return NULL; +} + +layout_object_t *layout_create_arc(const char *search_id, layer_id_t layer_id, int x, int y, int width, int height, int sa, int dir, int thickness, int clearance, multiple layout_flag_t flags) +{ + layout_search_t *s; + void *res; + pcb_layer_t *layer = pcb_get_layer(PCB->Data, layer_id); + + if (layer == NULL) + return NULL; + + res = layout_create_arc_(layer, x, y, width, height, sa, dir, thickness, clearance, flags); + return search_persist_created(search_id, layer_id, res, OM_ARC); +} + +layout_object_t *layout_create_text(const char *search_id, layer_id_t layer_id, int x, int y, int direction, int scale, const char *str, multiple layout_flag_t flags) +{ + layout_search_t *s; + void *res; + pcb_layer_t *layer = pcb_get_layer(PCB->Data, layer_id); + + if (layer == NULL) + return NULL; + + res = pcb_text_new(layer, pcb_font(PCB, 0, 1), x, y, direction, scale, pcb_strdup(str), get_flags(flags)); + return search_persist_created(search_id, layer_id, res, OM_ARC); +} + + + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c (revision 13657) @@ -0,0 +1,49 @@ +#include +#include +#include "layout.h" +#include "src/hid.h" +#include "src/error.h" + +static pcb_hid_t *ddh = NULL; + +#define need_ddh if (ddh == NULL) return + + +int debug_draw_request(void) +{ + ddh = pcb_gui->request_debug_draw(); + if (ddh == NULL) + return 0; + return 1; +} + +void debug_draw_flush(void) +{ + need_ddh; + pcb_gui->flush_debug_draw(); +} + +void debug_draw_finish(dctx_t *ctx) +{ + need_ddh; + ddh->destroy_gc(ctx->gc); + pcb_gui->finish_debug_draw(); + free(ctx); + ddh = NULL; +} + +dctx_t *debug_draw_dctx(void) +{ + dctx_t *ctx; + pcb_hid_gc_t gc; + need_ddh(NULL); + gc = ddh->make_gc(); + if (gc == NULL) { + pcb_message(PCB_MSG_ERROR, "debug_draw_dctx(): failed to make a new gc on ddh %p\n", (void *)ddh); + return NULL; + } + + ctx = malloc(sizeof(dctx_t)); + ctx->hid = ddh; + ctx->gc = gc; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c (revision 13657) @@ -0,0 +1,45 @@ +#include +#include +#include "layout.h" +#include "src/hid.h" +#include "src/error.h" + +#define setup(func) \ + pcb_hid_gc_t gc = ctx->gc; \ + pcb_hid_t *hid = ctx->hid; \ + if ((hid == NULL) && (gc == NULL)) pcb_message(PCB_MSG_ERROR, "%s failed because of invalid hid or gc\n", func); \ + if ((hid == NULL) && (gc == NULL)) return + + +void draw_set_color(dctx_t *ctx, const char *name) +{ + setup("draw_set_color"); + hid->set_color(gc, name); +} + +/*void set_line_cap(dctx_t *ctx, pcb_cap_style_t style_);*/ +void draw_set_line_width(dctx_t *ctx, int width) +{ + setup("draw_set_line_width"); + hid->set_line_width(gc, width); +} + +void draw_set_draw_xor(dctx_t *ctx, int xor) +{ + setup("draw_set_draw_xor"); + hid->set_draw_xor(gc, xor); +} + + +void draw_set_draw_faded(dctx_t *ctx, int faded) +{ + setup("draw_set_draw_faded"); + hid->set_draw_faded(gc, faded); +} + +void pcb_line_draw(dctx_t *ctx, int x1, int y1, int x2, int y2) +{ + setup("draw_line"); + hid->draw_line(gc, x1, y1, x2, y2); +} + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf (revision 13657) @@ -0,0 +1,18 @@ +@/local/headers + layout.h + +@/local/srcs + create.c layers.c object.c page.c search.c coord.c debug_draw.c draw.c + +@/local/file_name + layout + +@/local/inst_path + layout + +@/local/CFLAGS + -I.. -I$(PCB_SRC) $(PCB_CFLAGS) -D###/target/sys/class### + +@@/local/hook/postall + PCB_GPMI_ROOT=../../.. + include $(PCB_GPMI_ROOT)/Makefile.config Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c (revision 13657) @@ -0,0 +1,112 @@ +#include +#include +#include "layout.h" +#include "src/board.h" +#include "src/const.h" +#include "src/draw.h" +#include "src/conf_core.h" +#include "src/layer.h" +#include "src/layer_ui.h" +#include "src/layer_vis.h" +#include "src/compat_misc.h" + +#define LAYER_SEARCH_MAX 32 + +#define layer_check(layer) \ + if ((layer < 0) || (layer >= PCB_MAX_LAYER+2)) \ + return + + +void layout_switch_to_layer(int layer) +{ + layer_check(layer); + pcb_layervis_change_group_vis(layer, pcb_true, pcb_true); + pcb_redraw(); +} + +layer_id_t layout_get_current_layer() +{ + return pcb_layer_id(PCB->Data, CURRENT); +} + +int layout_resolve_layer(const char *name) +{ + int n; + if (name == NULL) + return -2; + for(n = 0; n < PCB_MAX_LAYER + 2; n++) + if ((PCB->Data->Layer[n].name != NULL) && (strcmp(PCB->Data->Layer[n].name, name) == 0)) + return n; + return -1; +} + +int layout_get_max_possible_layer() +{ + return PCB_MAX_LAYER+2; +} + +int layout_get_max_layer() +{ + return pcb_max_layer; +} + +const char *layout_layer_name(int layer) +{ + layer_check(layer)(""); + return PCB->Data->Layer[layer].name; +} + +const char *layout_layer_color(int layer) +{ + layer_check(layer)(""); + return PCB->Data->Layer[layer].meta.real.color; +} + +int layout_layer_field(int layer, layer_field_t fld) +{ + layer_check(layer)(-1); + switch(fld) { + case LFLD_NUM_LINES: return linelist_length(&(PCB->Data->Layer[layer].Line)); + case LFLD_NUM_TEXTS: return textlist_length(&(PCB->Data->Layer[layer].Text)); + case LFLD_NUM_POLYS: return polylist_length(&(PCB->Data->Layer[layer].Polygon)); + case LFLD_NUM_ARCS: return arclist_length(&(PCB->Data->Layer[layer].Arc)); + case LFLD_VISIBLE: return PCB->Data->Layer[layer].meta.real.vis; + case LFLD_NODRC: return PCB->Data->Layer[layer].meta.real.no_drc; + } + return -1; +} + +int layer_flag_is_set(unsigned int flags, multiple layer_type_t flg) +{ + return !!(flags & flg); +} + +layer_id_t layer_list(multiple layer_type_t flags, int idx) +{ + pcb_layer_id_t ids[LAYER_SEARCH_MAX]; + int len = pcb_layer_list(PCB, flags, ids, LAYER_SEARCH_MAX); + if (idx < 0) + return len; + if (idx >= len) + return -1; + return ids[idx]; +} + +layer_id_t layer_list_any(multiple layer_type_t flags, int idx) +{ + pcb_layer_id_t ids[LAYER_SEARCH_MAX]; + int len = pcb_layer_list_any(PCB, flags, ids, LAYER_SEARCH_MAX); + if (idx < 0) + return len; + if (idx >= len) + return -1; + return ids[idx]; +} + +layer_id_t uilayer_alloc(const char *name, const char *color) +{ + pcb_layer_t *l = pcb_uilayer_alloc("script", pcb_strdup(name), pcb_strdup(color)); + if (l == NULL) + return -1; + return pcb_layer_id(PCB->Data, l); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h (revision 13657) @@ -0,0 +1,323 @@ +#include +#include "src/global_typedefs.h" +#include "src/rtree.h" +#include "src/data.h" +#include "src/layer.h" +#include "src/pcb-printf.h" + +#undef snprintf +#define snprintf pcb_snprintf + +typedef long int layer_id_t; + +/* Object type search mask bits */ +typedef enum layout_object_mask_e { + OM_LINE = 1, /* lines (traces, silk lines, not font) */ + OM_TEXT = 2, /* text written using the font */ + OM_POLYGON = 4, /* polygons, including rectangles */ + OM_ARC = 8, /* arcs, circles */ + OM_VIA = 16, /* vias and holes which are not part of a footprint */ + OM_PIN = 32, /* pins/pads of a footprint */ + + OM_ANY = 0xffff /* shorthand for "find anything" */ +} layout_object_mask_t; +gpmi_keyword *kw_layout_object_mask_e; /* of layout_object_mask_t */ + +/* Which coordinate of the object is referenced */ +typedef enum layout_object_coord_e { +/* X/Y coords */ + OC_BX1 = 1, /* bounding box X1 */ + OC_BX2 = 2, /* bounding box X2 */ + OC_BY1 = 3, /* bounding box Y1 */ + OC_BY2 = 4, /* bounding box Y2 */ + OC_P1X = 5, /* point 1 X */ + OC_P2X = 6, /* point 2 X */ + OC_P1Y = 7, /* point 1 Y */ + OC_P2Y = 8, /* point 2 Y */ + OC_OBJ = 9, /* the whole object */ + +/* point aliases for X/Y coords */ + OC_P1 = 5, /* point 1 is P1X*/ + OC_P2 = 6 /* point 2 is P2X */ + +} layout_object_coord_t; +gpmi_keyword *kw_layout_object_coord_e; /* of layout_object_coord_t */ + + +typedef enum layout_flag_e { + FL_NONE = 0, + FL_SHOWNUMBER = 0x00000001, + FL_LOCALREF = 0x00000002, + FL_CHECKPLANS = 0x00000004, + FL_SHOWDRC = 0x00000008, + FL_RUBBERBAND = 0x00000010, + FL_DESCRIPTION = 0x00000020, + FL_NAMEONPCB = 0x00000040, + FL_AUTODRC = 0x00000080, + FL_ALLDIRECTION = 0x00000100, + FL_SWAPSTARTDIR = 0x00000200, + FL_UNIQUENAME = 0x00000400, + FL_CLEARNEW = 0x00000800, + FL_SNAPPIN = 0x00001000, + FL_SHOWMASK = 0x00002000, + FL_THINDRAW = 0x00004000, + FL_ORTHOMOVE = 0x00008000, + FL_LIVEROUTE = 0x00010000, + FL_THINDRAWPOLY = 0x00020000, + FL_LOCKNAMES = 0x00040000, + FL_ONLYNAMES = 0x00080000, + FL_NEWFULLPOLY = 0x00100000, + FL_HIDENAMES = 0x00200000, + + FL_THERMALSTYLE1 = 0x08000000, + FL_THERMALSTYLE2 = 0x10000000, + FL_THERMALSTYLE3 = 0x20000000, + FL_THERMALSTYLE4 = 0x40000000, + FL_THERMALSTYLE5 = 0x80000000 +} layout_flag_t; +gpmi_keyword *kw_layout_flag_e; /* of layout_flag_t */ + +/* Layer type bitfield */ +typedef enum layer_flag_e { + LYT_TOP = PCB_LYT_TOP, + LYT_BOTTOM = PCB_LYT_BOTTOM, + LYT_INTERN = PCB_LYT_INTERN, + LYT_LOGICAL = PCB_LYT_LOGICAL, + LYT_ANYWHERE = PCB_LYT_ANYWHERE, + + LYT_COPPER = PCB_LYT_COPPER, + LYT_SILK = PCB_LYT_SILK, + LYT_MASK = PCB_LYT_MASK, + LYT_PASTE = PCB_LYT_PASTE, + LYT_OUTLINE = PCB_LYT_OUTLINE, + LYT_RAT = PCB_LYT_RAT, + LYT_INVIS = PCB_LYT_INVIS, + LYT_ASSY = PCB_LYT_ASSY, + LYT_FAB = PCB_LYT_FAB, + LYT_PDRILL = PCB_LYT_PDRILL, + LYT_UDRILL = PCB_LYT_UDRILL, + LYT_ANYTHING = PCB_LYT_ANYTHING, + + LYT_VIRTUAL = PCB_LYT_VIRTUAL, + LYT_ANYPROP = PCB_LYT_ANYPROP +} layer_type_t; +gpmi_keyword *kw_layer_flag_e; /* of layer_type_t */ + + + +typedef struct layout_object_s { + layout_object_mask_t type; + union { + pcb_line_t *l; + pcb_text_t *t; + pcb_poly_t *p; + pcb_arc_t *a; + pcb_pin_t *v; + pcb_pin_t *pin; + } obj; + pcb_layer_id_t layer; +} layout_object_t; + + +typedef struct layout_search_s { + layout_object_mask_t searching; /* during the search, this field is used to communicate with the callback */ + int used, alloced; + layout_object_t *objects; + int layer; +} layout_search_t; + +/* -- search -- (search.c) */ +/* creates a new search and adds all objects that matches obj_types mask within the given rectangle on the current layer + Arguments: + search_ID: unique name of the search (overwrites existing search on the same name) + obj_types: on or more object types + x1, y1, x2, y2: box the search is done within (PCB coords) + Returns the number of object on the search list. */ +int layout_search_box(const char *search_ID, layout_object_mask_t obj_types, int x1, int y1, int x2, int y2); + +/* creates a new search and adds all selected objects + Arguments: + search_ID: unique name of the search (overwrites existing search on the same name) + obj_types: on or more object types + Returns the number of object on the search list. */ +int layout_search_selected(const char *search_ID, multiple layout_object_mask_t obj_types); + +/* creates a new search and adds all found objects (the green highlight) + Arguments: + search_ID: unique name of the search (overwrites existing search on the same name) + obj_types: on or more object types + Returns the number of object on the search list. */ +int layout_search_found(const char *search_ID, multiple layout_object_mask_t obj_types); + +/* Returns the nth object from a search list (or NULL pointer if n is beyond the list) */ +layout_object_t *layout_search_get(const char *search_ID, int n); + +/* Creates a new, empty search list. Useful for search list manipulation. + Returns 0 on succes. */ +int layout_search_empty(const char *search_ID); + +/* Frees all memory related to a search. Returns 0 on success. + Argument: + search_ID: unique name of the search (requires an existing search) */ +int layout_search_free(const char *search_ID); + +/* -- object accessors -- (object.c) */ +/* Return the requested coord of an object; except for the bounding box + coordinates, the meaning of coordinates are object-specific. + Point 1 and point 2 are usually endpoints of the object (line, arc), + "the whole object" coordinate is a central point. */ +int layout_obj_coord(layout_object_t *obj, layout_object_coord_t coord); + +/* Return the type of an object (always a single bit) */ +layout_object_mask_t layout_obj_type(layout_object_t *obj); + +/* Change location of an object or parts of the object (like move endpoint of a line); + Arguments: + obj: the object + coord: which coordinate to drag (e.g. move only the endpoint) + dx, dy: relative x and y coordinates the selected coordinate is displaced by + Returns 0 on success */ +int layout_obj_move(layout_object_t *obj, layout_object_coord_t coord, int dx, int dy); + +/* change angles of an arc; start and delate are relative if relative is non-zero; returns 0 on success */ +int layout_arc_angles(layout_object_t *obj, int relative, int start, int delta); + +/* -- create new objects -- (create.c) */ +/* if search_id is not empty, a referece to the new object is stored + on that search list and a persistent pointer is returned on success. If + search_id is empty, a temporary pointer is returned that should not be + used for anything else than checking against NULL. */ + +/* create a line */ +layout_object_t *layout_create_line(const char *search_id, layer_id_t layer_id, int x1, int y1, int x2, int y2, int thickness, int clearance, multiple layout_flag_t flags); + +/* same as layout_create_line(), but appends the result to a list and + returns the index of the new object on the list (can be used as n for + layour_search_get) +int layout_lcreate_line(const char *search_ID, int x1, int y1, int x2, int y2, int thickness, int clearance, multiple layout_flag_t flags);*/ + +/* create a named via */ +layout_object_t *layout_create_via(const char *search_id, int x, int y, int thickness, int clearance, int mask, int hole, const char *name, multiple layout_flag_t flags); + +/* create a new arc; sa is start angle, dir is delta angle */ +layout_object_t *layout_create_arc(const char *search_id, layer_id_t layer_id, int x, int y, int width, int height, int sa, int dir, int thickness, int clearance, multiple layout_flag_t flags); + +/* create a new text (TODO) */ +layout_object_t *layout_create_text(const char *search_id, layer_id_t layer_id, int x, int y, int direction, int scale, const char *str, multiple layout_flag_t flags); + +/* -- layer manipulation -- (layers.c) */ +/* Field name of the layer structure */ +typedef enum layer_field_e { + LFLD_NUM_LINES, /* number of lines on the layer */ + LFLD_NUM_TEXTS, /* number of texts on the layer */ + LFLD_NUM_POLYS, /* number of polygons on the layer */ + LFLD_NUM_ARCS, /* number of arcs on the layer */ + LFLD_VISIBLE, /* non-zero if the layer is visible */ + LFLD_NODRC /* non-zero if the layer doesn't use DRC */ +} layer_field_t; + +/* switch to layer (further layer-specific actions will take place there) */ +void layout_switch_to_layer(int layer); + +/* returns the number of the current layer */ +layer_id_t layout_get_current_layer(); + +/* resolve layer number by name (case sensitive); returns negative number if not found */ +int layout_resolve_layer(const char *name); + +/* return the theoretical number of layers supported by PCB */ +int layout_get_max_possible_layer(); + +/* return the actual number of layers on the current design */ +int layout_get_max_layer(); + +/* return the name of a layer */ +const char *layout_layer_name(int layer); + +/* return the color of a layer */ +const char *layout_layer_color(int layer); + +/* return an integer field of a layer */ +int layout_layer_field(int layer, layer_field_t fld); + + +/* -- page manipulation -- (page.c) */ +/* query or set width and height of the drawing */ +int layout_get_page_width(); +int layout_get_page_height(); +void layout_set_page_size(int width, int height); + +/* -- coordinate system -- (coord.c) */ +double mil2pcb_multiplier(); +double mm2pcb_multiplier(); +const char *current_grid_unit(); + +typedef struct dctx_s { + void *hid; + void *gc; +} dctx_t; + +/* -- debug draw GC -- */ +/* Initialize debug drawing; returns 1 if worked, 0 if denied */ +int debug_draw_request(void); + +/* Flush the drawing */ +void debug_draw_flush(void); + +/* Finish (close) drawing */ +void debug_draw_finish(dctx_t *ctx); + +/* Get the draw context of debug draw */ +dctx_t *debug_draw_dctx(void); + +/* -- draw on a GC -- */ + +/* Debug draw style: set drawing color */ +void draw_set_color(dctx_t *ctx, const char *name); +/*void set_line_cap(dctx_t *ctx, pcb_cap_style_t style_);*/ + +/* Debug draw style: set line width */ +void draw_set_line_width(dctx_t *ctx, int width); + +/* Debug draw style: set whether drawing should happen in xor */ +void draw_set_draw_xor(dctx_t *ctx, int xor); + +/* Debug draw style: set whether drawing should happen in faded mode */ +void draw_set_draw_faded(dctx_t *ctx, int faded); + +/* Debug draw: draw a line using the current style settings */ +void pcb_line_draw(dctx_t *ctx, int x1_, int y1_, int x2_, int y2_); + +/* +void pcb_arc_draw(dctx_t *ctx, int cx_, int cy_, int xradius_, int yradius_, double start_angle_, double delta_angle_); +void draw_rect(dctx_t *ctx, int x1_, int y1_, int x2_, int y2_); +void fill_circle(dctx_t *ctx, int cx_, int cy_, int radius_); +void fill_polygon(dctx_t *ctx, int n_ints_, int *x_, int *y_); +void fill_pcb_polygon(dctx_t *ctx, pcb_poly_t *poly, const pcb_box_t *clip_box); +void thindraw_pcb_polygon(dctx_t *ctx, pcb_poly_t *poly, const pcb_box_t *clip_box); +void fill_pcb_pad(dctx_t *ctx, pcb_pad_t *pad, pcb_bool clip, pcb_bool mask); +void thindraw_pcb_pad(dctx_t *ctx, pcb_pad_t *pad, pcb_bool clip, pcb_bool mask); +void fill_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t *pv, pcb_bool drawHole, pcb_bool mask); +void thindraw_pcb_pv(pcb_hid_gc_t fg_gc, pcb_hid_gc_t bg_gc, pcb_pin_t *pv, pcb_bool drawHole, pcb_bool mask); +void fill_rect(dctx_t *ctx, int x1_, int y1_, int x2_, int y2_); +*/ + +/* Returns 1 if flg is set in flags */ +int layer_flag_is_set(unsigned int flags, multiple layer_type_t flg); + +/* List layers IDs with exact match on flags. If idx is -1, return the + length of matches, else return the idxth match, */ +layer_id_t layer_list(multiple layer_type_t flags, int idx); + +/* List layers IDs with any match on flags. If idx is -1, return the + length of matches, else return the idxth match, */ +layer_id_t layer_list_any(multiple layer_type_t flags, int idx); + +/* Allocate a new UI layer */ +layer_id_t uilayer_alloc(const char *name, const char *color); + +/* Internal: */ +/* Append a newly created object to a search list or put it in a static var and + return the object */ +nowrap layout_object_t *search_persist_created(const char *search_id, pcb_layer_id_t layer, void *obj, layout_object_mask_t type); + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c (revision 13657) @@ -0,0 +1,157 @@ +#include +#include +#include "layout.h" +#include "src/change.h" +#include "src/const.h" +#include "src/board.h" +#include "src/move.h" +#include "src/conf_core.h" +#include "src/layer.h" + +int layout_obj_coord(layout_object_t *obj, layout_object_coord_t coord) +{ + pcb_any_obj_t *o; + + if (obj == NULL) + return -1; + + o = (pcb_any_obj_t *)obj->obj.l; + + /* bounding box is the same for any type */ + switch (coord) { + case OC_BX1: return o->BoundingBox.X1; + case OC_BX2: return o->BoundingBox.X2; + case OC_BY1: return o->BoundingBox.Y1; + case OC_BY2: return o->BoundingBox.Y2; + case OC_OBJ: return -1; + default: /* avoids warnings for unhandled requests we handle later, per object type */ + ; + } + + switch(obj->type) { + case OM_LINE: + switch (coord) { + case OC_P1X: return obj->obj.l->Point1.X; + case OC_P2X: return obj->obj.l->Point2.X; + case OC_P1Y: return obj->obj.l->Point1.Y; + case OC_P2Y: return obj->obj.l->Point2.Y; + default: /* avoids warnings for unhandled requests we handled above */ + ; + } + break; + case OM_TEXT: + switch (coord) { + case OC_P1X: + case OC_P2X: return obj->obj.t->X; + case OC_P1Y: + case OC_P2Y: return obj->obj.t->Y; + default: /* avoids warnings for unhandled requests we handled above */ + ; + } + break; + case OM_VIA: + switch (coord) { + case OC_P1X: + case OC_P2X: return obj->obj.v->X; + case OC_P1Y: + case OC_P2Y: return obj->obj.v->Y; + default: /* avoids warnings for unhandled requests we handled above */ + ; + } + break; + case OM_PIN: + switch (coord) { + case OC_P1X: + case OC_P2X: return obj->obj.pin->X; + case OC_P1Y: + case OC_P2Y: return obj->obj.pin->Y; + default: /* avoids warnings for unhandled requests we handled above */ + ; + } + break; + } + + return -1; +} + +layout_object_mask_t layout_obj_type(layout_object_t *obj) +{ + if (obj == NULL) + return 0; + return obj->type; +} + +int layout_obj_move(layout_object_t *obj, layout_object_coord_t coord, int dx, int dy) +{ + void *what = NULL;; + pcb_layer_t *ly; + + if (obj == NULL) + return -1; + + ly = pcb_get_layer(PCB->Data, obj->layer); + if (ly == NULL) + return -1; + + switch(obj->type) { + case OM_LINE: + switch(coord) { + case OC_OBJ: + pcb_move_obj(PCB_TYPE_LINE_POINT, ly, obj->obj.l, &(obj->obj.l->Point2), dx, dy); + /* intended falltrough */ + case OC_P1X: + case OC_P1Y: what = &(obj->obj.l->Point1); break; + case OC_P2X: + case OC_P2Y: what = &(obj->obj.l->Point2); break; + default: /* we do not handle anything else for now */ + ; + } + pcb_move_obj(PCB_TYPE_LINE_POINT, ly, obj->obj.l, what, dx, dy); + return 0; + case OM_TEXT: + pcb_move_obj(PCB_TYPE_TEXT, ly, obj->obj.t, obj->obj.t, dx, dy); + return 0; + case OM_VIA: + pcb_move_obj(PCB_TYPE_VIA, obj->obj.v, obj->obj.v, obj->obj.v, dx, dy); + return 0; + case OM_PIN: + pcb_move_obj(PCB_TYPE_PIN, obj->obj.pin, obj->obj.pin, obj->obj.pin, dx, dy); + return 0; + case OM_ARC: + switch(coord) { + case OC_OBJ: + pcb_move_obj(PCB_TYPE_ARC, ly, obj->obj.a, obj->obj.a, dx, dy); + return 0; + default: /* we do not handle anything else for now */ + ; + } + /*TODO: move endpoints! */ + break; + case OM_POLYGON: + if (obj->layer != -1) { + pcb_move_obj(PCB_TYPE_POLY, PCB->Data->Layer + obj->layer, obj->obj.p, obj->obj.p, dx, dy); + return 0; + } + } + return -1; +} + +int layout_arc_angles(layout_object_t *obj, int relative, int start, int delta) +{ + pcb_layer_t *ly; + + ly = pcb_get_layer(PCB->Data, obj->layer); + if (ly == NULL) + return -1; + + if (obj == NULL) + return -1; + if (obj->type != OM_ARC) + return 1; + if (relative) { + start += obj->obj.a->StartAngle; + delta += obj->obj.a->Delta; + } + pcb_arc_set_angles(ly, obj->obj.a, start, delta); + return 0; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c (revision 13657) @@ -0,0 +1,19 @@ +#include "layout.h" +#include "src/board.h" +#include "src/change.h" + +int layout_get_page_width() +{ + return PCB->MaxWidth; +} + +int layout_get_page_height() +{ + return PCB->MaxHeight; +} + +void layout_set_page_size(int width, int height) +{ + pcb_board_resize(MIN(PCB_MAX_COORD, MAX(width, PCB_MIN_SIZE)), MIN(PCB_MAX_COORD, MAX(height, PCB_MIN_SIZE))); +} + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c (revision 13657) @@ -0,0 +1,217 @@ +#include +#include +#include +#include +#include "src/board.h" +#include "src/conf_core.h" +#include "src/layer.h" +#include "layout.h" +#include "config.h" + +static inline layout_object_t *search_append(layout_search_t *s, void *obj) +{ + layout_object_t *o; + if (s->used >= s->alloced) { + s->alloced += 256; + s->objects = realloc(s->objects, s->alloced * sizeof(layout_object_t)); + } + o = s->objects + s->used; + s->used++; + o->type = s->searching; + o->layer = s->layer; + switch(s->searching) { + case OM_LINE: o->obj.l = obj; break; + case OM_TEXT: o->obj.t = obj; break; + case OM_POLYGON: o->obj.p = obj; break; + case OM_ARC: o->obj.a = obj; break; + case OM_VIA: o->obj.v = obj; break; + case OM_PIN: o->obj.pin = obj; break; + default: + assert(!"Unimplemented object type"); + } + return o; +} + +static pcb_r_dir_t search_callback (const pcb_box_t * b, void *cl) +{ + search_append(cl, (void *)b); + return PCB_R_DIR_FOUND_CONTINUE; +} + +hash_t *layout_searches = NULL; +static layout_search_t *new_search(const char *search_ID) +{ + layout_search_t *s; + layout_search_free(search_ID); + + if (layout_searches == NULL) { + layout_searches = hash_create(64, gpmi_hash_ptr); + assert(layout_searches != NULL); + } + + s = calloc(sizeof(layout_search_t), 1); + + hash_store(layout_searches, search_ID, s); + return s; +} + +int layout_search_empty(const char *search_ID) +{ + layout_search_t *s = new_search(search_ID); + if (s != NULL) + return 0; + return -1; +} + + +int layout_search_box(const char *search_ID, layout_object_mask_t obj_types, int x1, int y1, int x2, int y2) +{ + pcb_box_t spot; + layout_search_t *s = new_search(search_ID); + + spot.X1 = x1; + spot.Y1 = y1; + spot.X2 = x2; + spot.Y2 = y2; + + s->layer = -1; + if (obj_types & OM_LINE) { + s->searching = OM_LINE; + pcb_r_search(CURRENT->line_tree, &spot, NULL, search_callback, s, NULL); + } + + if (obj_types & OM_TEXT) { + s->searching = OM_TEXT; + pcb_r_search(CURRENT->text_tree, &spot, NULL, search_callback, s, NULL); + } + + if (obj_types & OM_ARC) { + s->searching = OM_ARC; + pcb_r_search(CURRENT->arc_tree, &spot, NULL, search_callback, s, NULL); + } + + if (obj_types & OM_VIA) { + s->searching = OM_VIA; + pcb_r_search(PCB->Data->via_tree, &spot, NULL, search_callback, s, NULL); + } + + if (obj_types & OM_PIN) { + s->searching = OM_PIN; + pcb_r_search(PCB->Data->pin_tree, &spot, NULL, search_callback, s, NULL); + } + + if (obj_types & OM_POLYGON) { + s->searching = OM_POLYGON; + for (s->layer = 0; s->layer < PCB_MAX_LAYER + 2; s->layer++) + pcb_r_search(PCB->Data->Layer[s->layer].polygon_tree, &spot, NULL, search_callback, s, NULL); + s->layer = -1; + } + + return s->used; +} + +/* PCB_FLAG_SELECTED */ + +typedef struct { + int flag; + layout_search_t *search; +} select_t; + +static void select_cb(void *obj_, void *ud) +{ + select_t *ctx = ud; + pcb_any_obj_t *obj = obj_; + if (PCB_FLAG_TEST(ctx->flag, obj)) + search_append(ctx->search, obj); +} + +#define select2(s, om, flag, lst) \ + do { \ + gdl_iterator_t it; \ + void *item; \ + select_t ctx; \ + ctx.flag = flag; \ + ctx.search = s; \ + s->searching = om; \ + linelist_foreach(lst, &it, item) select_cb(item, &ctx); \ + s->searching = 0; \ + } while(0) + +static int layout_search_flag(const char *search_ID, multiple layout_object_mask_t obj_types, int flag) +{ + pcb_cardinal_t l, n; + layout_search_t *s = new_search(search_ID); + pcb_layer_t *layer = PCB->Data->Layer; + + for (l =0; l < PCB_MAX_LAYER + 2; l++, layer++) { + s->layer = l; + select2(s, OM_ARC, flag, &layer->Arc); + select2(s, OM_LINE, flag, &layer->Line); + select2(s, OM_TEXT, flag, &layer->Text); + select2(s, OM_POLYGON, flag, &layer->Polygon); + } + select2(s, OM_VIA, flag, &PCB->Data->Via); +/* select2(s, OM_PIN, flag, &PCB->Data->Pin); /* TODO */ + + return s->used; +} +#undef select + +int layout_search_selected(const char *search_ID, multiple layout_object_mask_t obj_types) +{ + return layout_search_flag(search_ID, obj_types, PCB_FLAG_SELECTED); +} + +int layout_search_found(const char *search_ID, multiple layout_object_mask_t obj_types) +{ + return layout_search_flag(search_ID, obj_types, PCB_FLAG_FOUND); +} + +layout_object_t *layout_search_get(const char *search_ID, int n) +{ + const layout_search_t *s; + + s = hash_find(layout_searches, search_ID); + +/* printf("s=%p\n", (void *)s);*/ + if ((s == NULL) || (n < 0) || (n >= s->used)) + return NULL; + return s->objects+n; +} + +int layout_search_free(const char *search_ID) +{ + layout_search_t *s; + + if (layout_searches == NULL) + return 1; + + s = (layout_search_t *)hash_find(layout_searches, search_ID); + if (s != NULL) { + hash_del_key(layout_searches, search_ID); + free(s->objects); + free(s); + return 0; + } + return 2; +} + + +layout_object_t *search_persist_created(const char *search_id, pcb_layer_id_t layer, void *obj, layout_object_mask_t type) +{ + layout_search_t *s = NULL; + static layout_object_t temp; + + if ((search_id != NULL) && (*search_id != '\0')) + s = (layout_search_t *)hash_find(layout_searches, search_id); + + if (s == NULL) { + temp.layer = layer; + temp.obj.l = obj; + temp.type = type; + return &temp; + } + s->searching = type; + s->layer = layer; + return search_append(s, obj); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c (revision 13657) @@ -0,0 +1,251 @@ +#include +#include +#include +#include +#include +#include "src/global_typedefs.h" +#include "src/misc_util.h" +#include "src/compat_misc.h" +#include "src/conf_core.h" +#include "src/event.h" +#include "src/paths.h" +#include "src/error.h" +#include "src/plugins.h" +#include "src/hid_actions.h" +#include "scripts.h" +#include "manage_scripts.h" + +const char *gpmi_cookie = "GPMI plugin cookie"; + +/* This function is used to print a detailed GPMI error message */ +void gpmi_hid_print_error(gpmi_err_stack_t *entry, char *string) +{ + pcb_message(PCB_MSG_ERROR, "[GPMI] %s\n", string); +} + +static void start_timer(void); +static void timer_cb(pcb_hidval_t hv) +{ + static int mono = 0; + hid_gpmi_script_info_t *i; + for(i = hid_gpmi_script_info; i != NULL; i = i->next) + gpmi_call_RunTick(i->module, mono++); + start_timer(); +} + +static void start_timer(void) +{ + pcb_hidval_t hv; + pcb_gui->add_timer(timer_cb, 100, hv); +} + +int gpmi_hid_gui_inited = 0; +static void ev_gui_init(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + int ev; + char *ev_args; + hid_gpmi_script_info_t *i; + const char *menu = "/main_menu/Plugins/GPMI scripting/Scripts"; + + pcb_gui->create_menu(menu, "gpmi_scripts()", "S", "Altg", "Manage GPMI scripts", gpmi_cookie); + + ev = gpmi_event_find("ACTE_gui_init", &ev_args); + if (ev >= 0) { + for(i = hid_gpmi_script_info; i != NULL; i = i->next) + if (i->module != NULL) + gpmi_event(i->module, ev, argc, argv); + } + gpmi_hid_gui_inited = 1; + + start_timer(); +} + +static void cmd_reload(const char *name) +{ + hid_gpmi_script_info_t *i; + if (name != NULL) { + i = hid_gpmi_lookup(name); + if (i != NULL) + hid_gpmi_reload_module(i); + else + pcb_message(PCB_MSG_ERROR, "Script %s not found\n", name); + } + else { + for(i = hid_gpmi_script_info; i != NULL; i = i->next) + hid_gpmi_reload_module(i); + } +} + +static int action_gpmi_scripts(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (argc == 0) { + gpmi_hid_manage_scripts(); + return 0; + } + if (pcb_strcasecmp(argv[0], "reload") == 0) { + if (argc > 1) + cmd_reload(argv[1]); + else + cmd_reload(NULL); + } + else if (pcb_strcasecmp(argv[0], "load") == 0) { + if (argc == 3) { + if (hid_gpmi_load_module(NULL, argv[1], argv[2], NULL) == NULL) + pcb_message(PCB_MSG_ERROR, "Failed to load %s %s\n", argv[1], argv[2]); + } + else + pcb_message(PCB_MSG_ERROR, "Invalid number of arguments for load\n"); + } + else if (pcb_strcasecmp(argv[0], "unload") == 0) { + if (argc == 2) { + hid_gpmi_script_info_t *i = hid_gpmi_lookup(argv[1]); + if (i != NULL) { + if (gpmi_hid_script_unload(i) != 0) { + pcb_message(PCB_MSG_ERROR, "Failed to unload %s\n", argv[1]); + return 1; + } + } + else { + pcb_message(PCB_MSG_ERROR, "Failed to unload %s: not loaded\n", argv[1]); + return 1; + } + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid number of arguments for unload\n"); + return 1; + } + } + else { + pcb_message(PCB_MSG_ERROR, "Invalid arguments in gpmi_scripts()\n"); + return 1; + } + return 0; +} + +static int action_gpmi_rehash(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + cmd_reload(NULL); + return 0; +} + +static void register_actions() +{ + static pcb_hid_action_t act1, act2; + + act1.name = "gpmi_scripts"; + act1.need_coord_msg = NULL; + act1.description = "Manage gpmi scripts"; + act1.syntax = "TODO"; + act1.trigger_cb = action_gpmi_scripts; + pcb_hid_register_action(&act1, gpmi_cookie, 0); + + act2.name = "rehash"; + act2.need_coord_msg = NULL; + act2.description = "Reload all gpmi scripts"; + act2.syntax = "TODO"; + act2.trigger_cb = action_gpmi_rehash; + pcb_hid_register_action(&act2, gpmi_cookie, 0); +} + +static gpmi_package *pkg_scripts = NULL; + +static void load_base_and_cfg(void) +{ + char *dir, *libdirg, *libdirh, *wdir, *wdirh, *hdirh; + const char *home; + void **gpmi_asm_scriptname; + + libdirg = pcb_path_resolve_inplace(pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S "plugins", NULL), 0); + libdirh = pcb_path_resolve_inplace(pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S "plugins" PCB_DIR_SEPARATOR_S, HOST, NULL), 0); + wdirh = pcb_path_resolve_inplace(pcb_concat("plugins" PCB_DIR_SEPARATOR_S, HOST, NULL), 0); + wdir = pcb_concat("plugins", NULL); + + home = getenv ("PCB_RND_GPMI_HOME"); + if (home == NULL) + home = conf_core.rc.path.home; + + hdirh = pcb_path_resolve_inplace(pcb_concat(home, PCB_DIR_SEPARATOR_S ".pcb" PCB_DIR_SEPARATOR_S "plugins" PCB_DIR_SEPARATOR_S, HOST, NULL), 0); + + pcb_message(PCB_MSG_DEBUG, "gpmi dirs: lg=%s lh=%s wh=%s w=%s hh=%s\n", libdirg, libdirh, wdirh, wdir, hdirh); + + /* first add package search path to all host-specific plugin dirs + This is needed because a script installed in ~/.pcb/plugins/ *.conf + (added automatically from, the gui) + could depend on a package being anywhere else + */ + gpmi_path_insert(GPMI_PATH_PACKAGES, libdirh); + gpmi_path_insert(GPMI_PATH_PACKAGES, libdirg); + gpmi_path_insert(GPMI_PATH_PACKAGES, wdirh); + gpmi_path_insert(GPMI_PATH_PACKAGES, hdirh); + + /* the final fallback - append this as loading anything from here is arch-unsafe */ + gpmi_path_append(GPMI_PATH_PACKAGES, wdir); + + + gpmi_err_stack_enable(); + if (gpmi_pkg_load("gpmi_scripts", 0, NULL, NULL, &pkg_scripts)) + { + gpmi_err_stack_process_str(gpmi_hid_print_error); + abort(); + } + gpmi_err_stack_destroy(NULL); + + + gpmi_asm_scriptname = gpmi_pkg_resolve(pkg_scripts, "gpmi_scripts_asm_scriptname"); + assert(gpmi_asm_scriptname != NULL); + *gpmi_asm_scriptname = gpmi_hid_asm_scriptname; + + register_actions(); + pcb_event_bind(PCB_EVENT_GUI_INIT, ev_gui_init, NULL, gpmi_cookie); + + hid_gpmi_load_dir(libdirh, 0); + hid_gpmi_load_dir(libdirg, 0); + + dir = pcb_concat(PCBLIBDIR, PCB_DIR_SEPARATOR_S "plugins", NULL); + hid_gpmi_load_dir(dir, 1); + free(dir); + + if (home != NULL) { + hid_gpmi_load_dir (hdirh, 0); + + dir = pcb_path_resolve_inplace(pcb_concat(home, PCB_DIR_SEPARATOR_S ".pcb" PCB_DIR_SEPARATOR_S "plugins", NULL), 0); + hid_gpmi_load_dir(dir, 1); + free(dir); + } + + hid_gpmi_load_dir(wdirh, 0); + hid_gpmi_load_dir(wdir, 0); + + free(wdir); + free(wdirh); + free(libdirg); + free(libdirh); + free(hdirh); +} + +int pplg_check_ver_gpmi(int ver_needed) +{ + return 0; +} + +void pplg_uninit_gpmi(void) +{ + pcb_event_unbind_allcookie(gpmi_cookie); + pcb_hid_remove_actions_by_cookie(gpmi_cookie); + hid_gpmi_script_info_uninit(); + gpmi_pkg_unload(pkg_scripts); + gpmi_uninit(); +} + +int pplg_init_gpmi(void) +{ + gpmi_init(); + load_base_and_cfg(); + return 0; +} + +/* Workaround: can't call it gpmi.so so basename is gpmi_plugin thus init name must be that too for the loader */ +int pplg_init_gpmi_plugin(void) +{ + return pplg_init_gpmi(); +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h (revision 13657) @@ -0,0 +1,4 @@ +extern const char *gpmi_cookie; +extern int gpmi_hid_gui_inited; /* whether the pcb_gui is already initialized */ +void gpmi_hid_print_error(gpmi_err_stack_t *entry, char *string); + Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c (revision 13657) @@ -0,0 +1,244 @@ +#include +#include +#include +#include +#include +#include "src/global_typedefs.h" +#include "src/misc_util.h" +#include "src/event.h" +#include "gpmi_plugin.h" +#include "scripts.h" +#include "src/hid_attrib.h" + + +extern pcb_hid_t *pcb_gui; + +#define attr_make_label(attr, name_, help_) \ +do { \ + memset((attr), 0, sizeof(pcb_hid_attribute_t)); \ + (attr)->name = name_; \ + (attr)->help_text = help_; \ + (attr)->type = PCB_HATT_LABEL; \ +} while(0) + +#define attr_make_label_str(attr, name1, name2, help_) \ +do { \ + char *__names__; \ + __names__ = pcb_concat(name1, name2, NULL); \ + attr_make_label(attr, __names__, help_); \ +} while(0) + + +#define attr_make_enum(attr, name_, help_, enum_vals, default_item) \ +do { \ + memset((attr), 0, sizeof(pcb_hid_attribute_t)); \ + (attr)->name = name_; \ + (attr)->help_text = help_; \ + (attr)->type = PCB_HATT_ENUM; \ + (attr)->enumerations = enum_vals; \ + (attr)->default_val.int_value = default_item; \ +} while(0) + +static hid_gpmi_script_info_t *choose_script(const char **operations, int *operation) +{ + pcb_hid_attribute_t attr[3]; + pcb_hid_attr_val_t result[3]; + char **scrl, **s; + hid_gpmi_script_info_t *i; + int n, res; + + n = gpmi_hid_scripts_count(); + + scrl = malloc(sizeof(char *) * (n+1)); + for(i = hid_gpmi_script_info, n = 0; i != NULL; i = i->next, n++) { + char *basename; + + basename = strrchr(i->name, PCB_DIR_SEPARATOR_C); + if (basename == NULL) + basename = i->name; + else + basename++; + + scrl[n] = pcb_concat(basename, "\t", i->module_name, NULL); + } + scrl[n] = NULL; + + attr_make_enum(&attr[0], "script", "Select an item from the list of scripts loaded", (const char **)scrl, -1); + + if (operations != NULL) + attr_make_enum(&attr[1], "operation", "Choose what to do with the script", operations, *operation); + + res = pcb_gui->attribute_dialog(attr, 1 + (operations != NULL), result, "GPMI manage scripts - select script", "Select one of the scripts already loaded", NULL); + + /* free scrl slots before return */ + for(s = scrl; *s != NULL; s++) + free(*s); + + if (res) { + if (operation != NULL) + *operation = -1; + return NULL; + } + + if ((operations != NULL) && (operation != NULL)) + *operation = result[1].int_value; + +/* printf("res=%d\n", result[0].int_value);*/ + + if (result[0].int_value != -1) { + for(i = hid_gpmi_script_info, n = result[0].int_value; i != NULL && n != 0; i = i->next, n--); +/* printf("name=%s\n", i->name);*/ + return i; + } + return NULL; +} + +static hid_gpmi_script_info_t *load_script(void) +{ + char *fn, *ext; + hid_gpmi_script_info_t *info; + int default_mod = -1; + pcb_hid_attribute_t attr[3]; + pcb_hid_attr_val_t result[3]; + char *exts[] = { + ".tcl", "tcl", + ".lua", "lua", + ".awk", "mawk", + ".mawk", "mawk", + ".py", "python", + ".scm", "scheme", + ".rb", "mruby", + ".ruby", "mruby", + ".st", "stutter", + ".pas", "ghli", + ".pl", "perl", + ".php", "php", + ".sh", "cli", + ".bash", "cli", + NULL, NULL + }; + const char *modules[] = { "tcl", "lua", "mawk", "python","scheme", "mruby", + "stutter", "ghli", "perl", "php", "cli", NULL }; + + + fn = pcb_gui->fileselect("Load script", "Load a GPMI script", NULL, NULL, "gpmi_load_script", HID_FILESELECT_READ); + + if (fn == NULL) + return NULL; + + ext = strrchr(fn, '.'); + if (ext != NULL) { + char **s; + const char **i; + /* find the extension in the extension->module pairs */ + for(s = exts; s[0] != NULL; s+=2) + if (strcmp(ext, s[0]) == 0) + break; + + /* if found, look up the "default enum value" for that module */ + if (s[1] != NULL) { + int n; + for(i = modules, n = 0; *i != NULL; i++,n++) { + if (strcmp(*i, s[1]) == 0) { + default_mod = n; + break; + } + } + } + } + + attr_make_enum(&attr[0], "module", "Select a GPMI module to interpret the script", modules, default_mod); + + if (pcb_gui->attribute_dialog(attr, 1, result, "GPMI manage scripts - select module", "Select one of GPMI modules to interpret the script", NULL)) + return NULL; + + if (result[0].int_value < 0) + return NULL; + + info = hid_gpmi_load_module(NULL, modules[result[0].int_value], fn, NULL); + if (info == NULL) + pcb_gui->report_dialog("GPMI script load", "Error loading the script.\nPlease consult the message log for details."); + return info; +} + +static void script_details(hid_gpmi_script_info_t *i) +{ + pcb_hid_attribute_t attr[4]; + pcb_hid_attr_val_t result[4]; + char *cf; + + cf = i->conffile_name == NULL ? "" : i->conffile_name; + + + attr_make_label_str(&attr[0], "File name: ", i->name, "File name of the script (if not absolute, it's relative to the config file)"); + attr_make_label_str(&attr[1], "GPMI module: ", i->module_name, "Name of the GPMI module that is interpreting the script"); + attr_make_label_str(&attr[2], "Config file: ", cf, "Name of config file that requested the script to be loaded "); + pcb_gui->attribute_dialog(attr, 3, result, "GPMI manage scripts - script details", "Displaying detailed info on a script already loaded", NULL); + free((char *)attr[0].name); + free((char *)attr[1].name); + free((char *)attr[2].name); +} + +void gpmi_hid_manage_scripts(void) +{ + hid_gpmi_script_info_t *i; + static const char *err_no_script = "Error: you didn't select a script"; +#define CONSULT "Please consult the message log for details." + + const char *operations[] = {"show details...", "reload", "unload", "unload and remove from the config file", "load a new script...", "load a new script and add it in the config...", NULL}; + int op = 0; + i = choose_script(operations, &op); + switch(op) { + case 0: + if (i != NULL) + script_details(i); + else + pcb_gui->report_dialog("GPMI script details", err_no_script); + break; + case 1: + if (i != NULL) { + i = hid_gpmi_reload_module(i); + if (i == NULL) + pcb_gui->report_dialog("GPMI script reload", "Error reloading the script.\nThe script is now unloaded.\n" CONSULT "\n(e.g. there may be syntax errors in the script source)."); + } + else + pcb_gui->report_dialog("GPMI script reload", err_no_script); + break; + case 2: + if (i != NULL) { + if (gpmi_hid_script_unload(i) != 0) + pcb_gui->report_dialog("GPMI script unload", "Error unloading the script.\n" CONSULT "\n"); + } + else + pcb_gui->report_dialog("GPMI script unload", err_no_script); + break; + case 3: + if (i != NULL) { + int r1, r2; + r1 = gpmi_hid_script_remove(i); + r2 = gpmi_hid_script_unload(i); + if (r1 || r2) { + char *msg; + msg = pcb_concat("Error:", + (r1 ? "couldnt't remove the script from the config file;" : ""), + (r2 ? "couldnt't unload the script;" : ""), + "\n" CONSULT "\n", NULL); + pcb_gui->report_dialog("GPMI script unload and remove", msg); + free(msg); + } + else + pcb_gui->report_dialog("GPMI script unload and remove", err_no_script); + } + break; + case 4: + load_script(); + break; + case 5: + i = load_script(); + if (i != NULL) { + if (gpmi_hid_script_addcfg(i) != 0) + pcb_gui->report_dialog("GPMI script add to config", "Error adding the script in user configuration.\n" CONSULT "\n"); + } + break; + } +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h (revision 13657) @@ -0,0 +1 @@ +void gpmi_hid_manage_scripts(void); Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c (revision 13657) @@ -0,0 +1,387 @@ +#include +#include +#include +#include +#include +#include +#include +#include "src/global_typedefs.h" +#include "src/misc_util.h" +#include "src/event.h" +#include "src/error.h" +#include "gpmi_plugin.h" +#include "scripts.h" +#include "src/conf_core.h" +#include "src/compat_fs.h" +#include "src/compat_misc.h" +#include "src/pcb-printf.h" +#include "src/safe_fs.h" + +#define CONFNAME "pcb-rnd-gpmi.conf" + +hid_gpmi_script_info_t *hid_gpmi_script_info = NULL; + +int gpmi_hid_scripts_count() +{ + int n; + hid_gpmi_script_info_t *i; + + for(i = hid_gpmi_script_info, n = 0; i != NULL; i = i->next, n++) ; + + return n; +} + +static void hid_gpmi_script_info_free(hid_gpmi_script_info_t *i) +{ + int ev; + char *ev_args; + ev = gpmi_event_find("ACTE_unload", &ev_args); + if (ev >= 0) + gpmi_event(i->module, ev, i->conffile_name); + + gpmi_mod_unload(i->module); + free(i->name); + free(i->module_name); + free(i->conffile_name); +} + +static hid_gpmi_script_info_t *hid_gpmi_script_info_add(hid_gpmi_script_info_t *i, gpmi_module *module, const char *name_, const char *module_name_, const char *conffile_name_) +{ + char *name, *module_name, *conffile_name; + /* make these copies before the free()'s because of reload calling us with + the same pointers... */ + name = pcb_strdup(name_); + module_name = pcb_strdup(module_name_); + if (conffile_name_ != NULL) + conffile_name = pcb_strdup(conffile_name_); + else + conffile_name = NULL; + + if (i == NULL) { + i = malloc(sizeof(hid_gpmi_script_info_t)); + i->next = hid_gpmi_script_info; + hid_gpmi_script_info = i; + } + else + hid_gpmi_script_info_free(i); + + i->module = module; + i->name = name; + i->module_name = module_name; + i->conffile_name = conffile_name; + return i; +} + +hid_gpmi_script_info_t *hid_gpmi_lookup(const char *name) +{ + hid_gpmi_script_info_t *i; + if (name == NULL) + return NULL; + for(i = hid_gpmi_script_info; i != NULL; i = i->next) + if (strcmp(name, i->name) == 0) + return i; + return NULL; +} + +/* Unload a script and remove it from the list */ +static void hid_gpmi_script_info_del(hid_gpmi_script_info_t *inf) +{ + hid_gpmi_script_info_t *i, *prev; + prev = NULL; + for(i = hid_gpmi_script_info; i != NULL; prev = i, i = i->next) { + if (i == inf) { + /* unlink */ + if (prev == NULL) + hid_gpmi_script_info = inf->next; + else + prev->next = inf->next; + hid_gpmi_script_info_free(inf); + free(inf); + return; + } + } +} + +/* Unload all scripts and remove them from the list */ +void hid_gpmi_script_info_uninit(void) +{ + hid_gpmi_script_info_t *i, *next; + + for(i = hid_gpmi_script_info; i != NULL; i = next) { + next = i->next; + hid_gpmi_script_info_free(i); + free(i); + } + hid_gpmi_script_info = NULL; +} + + +static const char *conf_dir = NULL; + +hid_gpmi_script_info_t *hid_gpmi_load_module(hid_gpmi_script_info_t *i, const char *module_name, const char *params, const char *config_file_name) +{ + gpmi_module *module; + + pcb_message(PCB_MSG_INFO, "Loading GPMI module %s with params %s...\n", module_name, params); + module = gpmi_mod_load(module_name, params); + if (module == NULL) { + pcb_message(PCB_MSG_ERROR, " Failed loading the script. Details:\n"); + gpmi_err_stack_process_str(gpmi_hid_print_error); + } + gpmi_err_stack_destroy(NULL); + + if (module != NULL) { + hid_gpmi_script_info_t *ri; + int ev; + + ri = hid_gpmi_script_info_add(i, module, params, module_name, config_file_name); + if ((ri != NULL) && (gpmi_hid_gui_inited)) { + char *ev_args; + /* If a script is loaded with a GUI already inited, send the event right after the load */ + ev = gpmi_event_find("ACTE_gui_init", &ev_args); + gpmi_event(ri->module, ev, 0, NULL); + } + return ri; + } + + return NULL; +} + +hid_gpmi_script_info_t *hid_gpmi_reload_module(hid_gpmi_script_info_t *i) +{ + hid_gpmi_script_info_t *r; + const char *old_cd; + + old_cd = conf_dir; + + if (i->conffile_name != NULL) { + char *end; + conf_dir = pcb_strdup(i->conffile_name); + end = strrchr(conf_dir, PCB_DIR_SEPARATOR_C); + if (end == NULL) { + free((char *)conf_dir); + conf_dir = NULL; + } + else + *end = '\0'; + } + else + conf_dir = NULL; + + r = hid_gpmi_load_module(i, i->module_name, i->name, i->conffile_name); + + if (conf_dir != NULL) + free((char *)conf_dir); + conf_dir = old_cd; + + return r; +} + +/* Read and parse gpmi config file fin; + if fout is NULL, take cfn as config name and load all modules, return number of modules loaded; + else write all lines to fout, but comment out the one whose second token matches cfn, return number of commented lines + +*/ + +static int cfgfile(FILE *fin, FILE *fout, char *cfn) +{ +char line[1024], *module, *params, *s; + int found = 0; + + while(!(feof(fin))) { + *line = '\0'; + fgets(line, sizeof(line), fin); + switch(*line) { + case '\0': + case '\n': + case '\r': + case '#': + /* Empty line or comment */ + if (fout != NULL) + fprintf(fout, "%s", line); + break; + default: + module = pcb_strdup(line); + params = module + strcspn(module, "\t "); + while((*params == ' ') || (*params == '\t')) { + *(params) = '\0'; + params++; + } + s = strchr(params, '\n'); + *s = '\0'; + if (fout == NULL) { + fprintf(stderr, " ...loading %s %s\n", module, params); + hid_gpmi_load_module(NULL, module, params, cfn); + found++; + } + else { + if (strcmp(params, cfn) == 0) { + fprintf(fout, "# removed from pcb-rnd GUI: "); + found++; + } + if (fout != NULL) + fprintf(fout, "%s", line); + } + free(module); + } + } + + return found; +} + +void hid_gpmi_load_dir(const char *dir, int add_pkg_path) +{ + FILE *f; + char *cfn; + + conf_dir = dir; + cfn = pcb_concat(dir, PCB_DIR_SEPARATOR_S, CONFNAME, NULL); +#ifdef CONFIG_DEBUG + fprintf(stderr, "pcb-gpmi: opening config: %s\n", cfn); +#endif + f = pcb_fopen(cfn, "r"); + if (f == NULL) { + free(cfn); +#ifdef CONFIG_DEBUG + fprintf(stderr, " ...failed\n"); +#endif + return; + } + + if (add_pkg_path) + gpmi_path_insert(GPMI_PATH_PACKAGES, dir); + + cfgfile(f, NULL, cfn); + + fclose(f); + free(cfn); + conf_dir = NULL; +} + +/* Dummy script name generator allows loading from any path */ +char *gpmi_hid_asm_scriptname(const void *info, const char *file_name) +{ + char buffer[1024]; + const char *cd; + + switch(*file_name) { + case '~': + file_name += 2; + if (conf_core.rc.path.home != NULL) { + pcb_snprintf(buffer, sizeof(buffer), "%s%c%s", conf_core.rc.path.home, PCB_DIR_SEPARATOR_C, file_name); + fprintf(stderr, "asm_scriptname FN=%s\n", buffer); + return pcb_strdup(buffer); + } + else { + fprintf(stderr, "pcb-gpmi error: can't access $HOME for substituting ~\n"); +#ifdef CONFIG_DEBUG + printf("FN=%s\n", file_name); +#endif + return pcb_strdup(file_name); + } + case PCB_DIR_SEPARATOR_C: /* full path */ + return pcb_strdup(file_name); + default: /* relative path - must be relative to the current conf_dir */ + if ((file_name[0] == '.') && (file_name[1] == PCB_DIR_SEPARATOR_C)) + file_name += 2; + if (conf_dir == NULL) + cd = "."; + else + cd = conf_dir; + pcb_snprintf(buffer, sizeof(buffer), "%s%c%s", cd, PCB_DIR_SEPARATOR_C, file_name); +#ifdef CONFIG_DEBUG + printf("FN=%s\n", buffer); +#endif + return pcb_strdup(buffer); + } + return NULL; +} + +int gpmi_hid_script_unload(hid_gpmi_script_info_t *i) +{ + hid_gpmi_script_info_del(i); + return 0; +} + +int gpmi_hid_script_remove(hid_gpmi_script_info_t *i) +{ + FILE *fin, *fout; + char *tmpfn; + int res; + + if (i->conffile_name == NULL) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_remove(): can't remove script from configs, the script is not loaded from a config.\n"); + return -1; + } + + fin = pcb_fopen(i->conffile_name, "r"); + if (fin == NULL) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_remove(): can't remove script from configs, can't open %s for read.\n", i->conffile_name); + return -1; + } + tmpfn = pcb_concat(i->conffile_name, ".tmp", NULL); + fout = pcb_fopen(tmpfn, "w"); + if (fout == NULL) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_remove(): can't remove script from configs, can't create %s.\n", tmpfn); + fclose(fin); + free(tmpfn); + return -1; + } + + res = cfgfile(fin, fout, i->name); + + fclose(fin); + fclose(fout); + + if (res < 1) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_remove(): can't remove script from configs, can't find the correspondign config line in %s\n", i->conffile_name); + free(tmpfn); + return -1; + } + + if (pcb_rename(tmpfn, i->conffile_name) != 0) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_remove(): can't remove script from configs, can't move %s to %s.\n", tmpfn, i->conffile_name); + free(tmpfn); + return -1; + } + + free(tmpfn); + return 0; +} + +int gpmi_hid_script_addcfg(hid_gpmi_script_info_t *i) +{ + char *fn; + const char *home; + FILE *f; + + home = getenv ("PCB_RND_GPMI_HOME"); + if (home == NULL) + home = conf_core.rc.path.home; + + if (conf_core.rc.path.home != NULL) { + fn = pcb_concat(home, PCB_DIR_SEPARATOR_S ".pcb", NULL); + pcb_mkdir(fn, 0755); + free(fn); + + fn = pcb_concat(home, PCB_DIR_SEPARATOR_S ".pcb" PCB_DIR_SEPARATOR_S "plugins", NULL); + pcb_mkdir(fn, 0755); + free(fn); + + fn = pcb_concat(home, PCB_DIR_SEPARATOR_S ".pcb" PCB_DIR_SEPARATOR_S "plugins" PCB_DIR_SEPARATOR_S, CONFNAME, NULL); + } + else + fn = pcb_concat("plugins" PCB_DIR_SEPARATOR_S, CONFNAME, NULL); + + f = pcb_fopen(fn, "a"); + if (f == NULL) { + pcb_message(PCB_MSG_ERROR, "gpmi_hid_script_addcfg: can't open %s for write\n", fn); + return -1; + } + + fprintf(f, "\n%s\t%s\n", i->module_name, i->name); + fclose(f); + + free(fn); + return 0; +} Index: tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h =================================================================== --- tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h (nonexistent) +++ tags/1.2.7/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h (revision 13657) @@ -0,0 +1,42 @@ +typedef struct hid_gpmi_script_info_s hid_gpmi_script_info_t; + +struct hid_gpmi_script_info_s { + char *name; + char *module_name; + char *conffile_name; + gpmi_module *module; + + hid_gpmi_script_info_t *next; +}; + +extern hid_gpmi_script_info_t *hid_gpmi_script_info; + +/* Load a GPMI module; if i is NULL, allocate a new slot on the list, else unload + i first and place the new module in place of i. */ +hid_gpmi_script_info_t *hid_gpmi_load_module(hid_gpmi_script_info_t *i, const char *module_name, const char *params, const char *config_file_name); + +/* Reload a script - useful if the source of the script has changed + Reloads a module already loaded; return NULL on error. */ +hid_gpmi_script_info_t *hid_gpmi_reload_module(hid_gpmi_script_info_t *i); + +/* look up a module by name - slow linear search */ +hid_gpmi_script_info_t *hid_gpmi_lookup(const char *name); + +void hid_gpmi_load_dir(const char *dir, int add_pkg_path); +char *gpmi_hid_asm_scriptname(const void *info, const char *file_name); + +/* Return the number of scripts (gpmi modules) loaded */ +int gpmi_hid_scripts_count(); + +/* Unload a script (also removes i from the list) - temporary effect, + the script will be loaded again on the next startup */ +int gpmi_hid_script_unload(hid_gpmi_script_info_t *i); + +/* Remove a script from the config file (but do not unload it now) */ +int gpmi_hid_script_remove(hid_gpmi_script_info_t *i); + +/* Edit a config file so that the script is in it */ +int gpmi_hid_script_addcfg(hid_gpmi_script_info_t *i); + +/* Uninit the script_info database, removing all scripts loaded */ +void hid_gpmi_script_info_uninit(void); Index: tags/1.2.7/src_plugins/hid_batch/Makefile =================================================================== --- tags/1.2.7/src_plugins/hid_batch/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/hid_batch/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_batch + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/hid_batch/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/hid_batch/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/hid_batch/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/hid_batch/batch.c =================================================================== --- tags/1.2.7/src_plugins/hid_batch/batch.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_batch/batch.c (revision 13657) @@ -0,0 +1,400 @@ +#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 "hid_draw_helpers.h" +#include "hid_nogui.h" +#include "hid_actions.h" +#include "hid_init.h" + +static const char *batch_cookie = "batch HID"; + +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 { + int nothing_interesting_here; +} hid_gc_s; + +static pcb_hid_attribute_t *batch_get_export_options(int *n_ret) +{ + return 0; +} + +/* ----------------------------------------------------------------------------- */ + +static char *prompt = NULL; + +static void uninit_batch(void) +{ + pcb_hid_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 int help(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_print_actions(); + return 0; +} + +static int info(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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); + } + return 0; +} + +pcb_hid_action_t batch_action_list[] = { + {"Help", 0, help} + , + {"Info", 0, 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; + + if (interactive) { + 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) { + printf("%s> ", prompt); + fflush(stdout); + } + if (fgets(line, sizeof(line) - 1, stdin) == NULL) { + uninit_batch(); + goto quit; + } + pcb_hid_parse_command(line); + } + + quit:; + batch_end(); +} + +static void batch_do_exit(pcb_hid_t *hid) +{ + batch_stay = 0; +} + +static void batch_parse_arguments(int *argc, char ***argv) +{ + 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + return 0; +} + +static pcb_hid_gc_t batch_make_gc(void) +{ + return 0; +} + +static void batch_destroy_gc(pcb_hid_gc_t gc) +{ +} + +static void batch_set_color(pcb_hid_gc_t gc, const char *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) +{ +} + +static void batch_set_crosshair(int x, int 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 pcb_hidval_t batch_add_block_hook(void (*func) (pcb_hidval_t data), pcb_hidval_t user_data) +{ + pcb_hidval_t ret; + ret.ptr = NULL; + return ret; +} + +static void batch_stop_block_hook(pcb_hidval_t mlpoll) +{ +} + +static int +batch_attribute_dialog(pcb_hid_attribute_t * attrs_, int n_attrs_, pcb_hid_attr_val_t * results_, const char *title_, const char *descr_, void *caller_data) +{ + return 0; +} + +static void batch_show_item(void *item) +{ +} + +static void batch_create_menu(const char *menu, const char *action, const char *mnemonic, const char *accel, const char *tip, const char *cookie) +{ +} + +static int batch_propedit_start(void *pe, int num_props, const char *(*query)(void *pe, const char *cmd, const char *key, const char *val, int idx)) +{ + printf("propedit start %d\n", num_props); + return 0; +} + +static void batch_propedit_end(void *pe) +{ + printf("propedit end\n"); +} + +static void *batch_propedit_add_prop(void *pe, const char *propname, int is_mutable, int num_vals) +{ + printf(" %s (%d) %s\n", propname, num_vals, is_mutable ? "mutable" : "immutable"); + return NULL; +} + +static void batch_propedit_add_value(void *pe, const char *propname, void *propctx, const char *value, int repeat_cnt) +{ + printf(" %s (%d)\n", value, repeat_cnt); +} + +static void batch_propedit_add_stat(void *pe, const char *propname, void *propctx, const char *most_common, const char *min, const char *max, const char *avg) +{ + printf(" [%s|%s|%s|%s]\n", most_common, min, max, avg); +} + + +#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); +} + +int pplg_init_hid_batch(void) +{ + 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.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.add_block_hook = batch_add_block_hook; + batch_hid.stop_block_hook = batch_stop_block_hook; + batch_hid.attribute_dialog = batch_attribute_dialog; + batch_hid.show_item = batch_show_item; + batch_hid.create_menu = batch_create_menu; + + batch_hid.propedit_start = batch_propedit_start; + batch_hid.propedit_end = batch_propedit_end; + batch_hid.propedit_add_prop = batch_propedit_add_prop; + batch_hid.propedit_add_value = batch_propedit_add_value; + batch_hid.propedit_add_stat = batch_propedit_add_stat; + + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, ev_pcb_changed, NULL, batch_cookie); + + pcb_hid_register_hid(&batch_hid); + return 0; +} + +static void batch_begin(void) +{ + PCB_REGISTER_ACTIONS(batch_action_list, batch_cookie) +} + +static void batch_end(void) +{ + pcb_hid_remove_actions_by_cookie(batch_cookie); +} Index: tags/1.2.7/src_plugins/hid_batch/hid_batch.pup =================================================================== --- tags/1.2.7/src_plugins/hid_batch/hid_batch.pup (nonexistent) +++ tags/1.2.7/src_plugins/hid_batch/hid_batch.pup (revision 13657) @@ -0,0 +1,6 @@ +$class hid +$short batch process (no-gui HID) +$long HID without GUI: read actions from stdin. +$state works +default buildin +autoload 1 Index: tags/1.2.7/src_plugins/hid_gtk2_gdk/Makefile =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gdk + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/hid_gtk2_gdk/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (revision 13657) @@ -0,0 +1,1481 @@ +#include "config.h" +#include "conf_core.h" + +#include + +#include "crosshair.h" +#include "clip.h" +#include "data.h" +#include "layer.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "hid_color.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/coord_conv.h" + +#include "../src_plugins/lib_gtk_config/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_config/lib_gtk_config.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)) 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_hid_t *me_pointer; + GdkGC *pixel_gc; + GdkGC *clip_gc; + + gchar *colorname; + pcb_coord_t width; + gint cap, join; + gchar xor_mask; + gint sketch_seq; +} hid_gc_s; + +static void draw_lead_user(render_priv_t *priv_); + +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 \p color_string has been allocated to \p 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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 /*&& !pinout */ ); + } + + if (idx >= 0 && idx < pcb_max_layer && ((flags & PCB_LYT_ANYTHING) != PCB_LYT_SILK)) + return /*pinout ? 1 : */ PCB->Data->Layer[idx].meta.real.vis; + + /* virtual layers */ + { + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return /* pinout ? 0 : */ PCB->InvisibleObjectsOn; + case PCB_LYT_SILK: + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags) /*|| pinout */ ) + return pcb_silk_on(PCB); + return 0; + case PCB_LYT_ASSY: + return 0; + case PCB_LYT_PDRILL: + case PCB_LYT_UDRILL: + return 1; + 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); + if (gc->colorname != NULL) + g_free(gc->colorname); + 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->colorname = g_strdup(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) { + for (i = 0; i < n; i++) + points[i].y = Vy(y); + 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, &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: + 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; +} + +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, &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; + + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/grid"), -1); + + 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, int arr_idx) +{ + 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], &priv->bg_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/background"), -1); + 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], &priv->offlimits_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/off_limit"), -1); + 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], &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_gdk_set_color(pcb_hid_gc_t gc, const char *name) +{ + static void *cache = 0; + static GdkColormap *colormap = NULL; + render_priv_t *priv = gport->render_priv; + pcb_hidval_t cval; + + if (name == NULL) { + fprintf(stderr, "ghid_gdk_set_color(): name = NULL, setting to magenta\n"); + name = "magenta"; + } + + if (name != gc->colorname) { + if (gc->colorname != NULL) + g_free(gc->colorname); + gc->colorname = g_strdup(name); + } + + if (!gc->pixel_gc) + return; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + + if (strcmp(name, "erase") == 0) { + } + else if (strcmp(name, "drill") == 0) { + 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 Trace_Cap: + case Round_Cap: + gc->cap = GDK_CAP_ROUND; + gc->join = GDK_JOIN_ROUND; + break; + case Square_Cap: + case Beveled_Cap: + gc->cap = GDK_CAP_PROJECTING; + gc->join = GDK_JOIN_MITER; + break; + } + 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->colorname); + + /* 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; + } + /* If not in direct mode then draw to the sketch and clip drawables */ + else + ghid_sketch_setup(priv); + } +} + +static int use_gc(pcb_hid_gc_t gc) +{ + 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_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->colorname); + ghid_gdk_set_line_width(gc, gc->width); + ghid_gdk_set_line_cap(gc, (pcb_cap_style_t) 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_NEGATIVE)); + + 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); + 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_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; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (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; + + 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); + 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_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); + 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); +} + +/* 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) +{ + static GdkPoint *points = 0; + static int npoints = 0; + int i; + render_priv_t *priv = gport->render_priv; + USE_GC(gc); + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + if (npoints < n_coords) { + npoints = n_coords + 1; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + for (i = 0; i < n_coords; i++) { + points[i].x = Vx(x[i]); + points[i].y = Vy(y[i]); + } + gdk_draw_polygon(priv->out_pixel, priv->pixel_gc, 1, points, n_coords); + if (priv->out_clip != NULL) + gdk_draw_polygon(priv->out_clip, priv->clip_gc, 1, points, n_coords); +} + +/* 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) +{ + static GdkPoint *points = 0; + static int npoints = 0; + int i; + render_priv_t *priv = gport->render_priv; + USE_GC(gc); + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (curr_drawing_mode == PCB_HID_COMP_NEGATIVE)); + + if (npoints < n_coords) { + npoints = n_coords + 1; + points = (GdkPoint *) realloc(points, npoints * sizeof(GdkPoint)); + } + for (i = 0; i < n_coords; i++) { + points[i].x = Vx(x[i]+dx); + points[i].y = Vy(y[i]+dy); + } + gdk_draw_polygon(priv->out_pixel, priv->pixel_gc, 1, points, n_coords); + if (priv->out_clip != NULL) + gdk_draw_polygon(priv->out_clip, priv->clip_gc, 1, points, n_coords); +} + +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; + render_priv_t *priv = gport->render_priv; + + assert((curr_drawing_mode == PCB_HID_COMP_POSITIVE) || (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; + + x1 = Vx(x1); + y1 = Vy(y1); + 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)); + + ctx.force = 0; + ctx.content.obj = NULL; + + 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); + ghid_gdk_draw_grid(); + + /* In some cases we are called with the crosshair still off */ + if (priv->attached_invalidate_depth == 0) + pcb_draw_attached(); + + /* In some cases we are called with the mark still off */ + if (priv->mark_invalidate_depth == 0) + pcb_draw_mark(); + + draw_lead_user(priv); + + 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--; + + 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(); + + 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(); + + 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) + 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, &cross_color); + } + x = DRAW_X(&gport->view, gport->view.crosshair_x); + y = DRAW_Y(&gport->view, 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, &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, &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, const 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; + + 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); + + /* call the drawing routine */ + expcall(>k2_gdk_hid, ctx); + + 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 pcb_hid_t *ghid_gdk_request_debug_draw(void) +{ + /* No special setup requirements, drawing goes into + * the backing pixmap. */ + return >k2_gdk_hid; +} + +static void ghid_gdk_flush_debug_draw(void) +{ + ghid_gdk_screen_update(); + gdk_flush(); +} + +static void ghid_gdk_finish_debug_draw(void) +{ + ghid_gdk_flush_debug_draw(); + /* No special tear down requirements + */ +} + +static void draw_lead_user(render_priv_t *priv) +{ + GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + GtkStyle *style = gtk_widget_get_style(gport->drawing_area); + int i; + pcb_lead_user_t *lead_user = &gport->lead_user; + pcb_coord_t radius = lead_user->radius; + pcb_coord_t width = PCB_MM_TO_COORD(LEAD_USER_WIDTH); + pcb_coord_t separation = PCB_MM_TO_COORD(LEAD_USER_ARC_SEPARATION); + static GdkGC *lead_gc = NULL; + static GdkColormap *colormap = NULL; + GdkColor lead_color; + + if (!lead_user->lead_user) + return; + + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + + if (lead_gc == NULL) { + lead_gc = gdk_gc_new(window); + gdk_gc_copy(lead_gc, style->white_gc); + gdk_gc_set_function(lead_gc, GDK_XOR); + gdk_gc_set_clip_origin(lead_gc, 0, 0); + lead_color.pixel = 0; + lead_color.red = (int) (65535. * LEAD_USER_COLOR_R); + lead_color.green = (int) (65535. * LEAD_USER_COLOR_G); + lead_color.blue = (int) (65535. * LEAD_USER_COLOR_B); + gdk_color_alloc(colormap, &lead_color); + gdk_gc_set_foreground(lead_gc, &lead_color); + } + + set_clip(priv, lead_gc); + gdk_gc_set_line_attributes(lead_gc, Vz(width), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); + + /* arcs at the approrpriate radii */ + + for (i = 0; i < LEAD_USER_ARC_COUNT; i++, radius -= separation) { + if (radius < width) + radius += PCB_MM_TO_COORD(LEAD_USER_INITIAL_RADIUS); + + /* Draw an arc at radius */ + gdk_draw_arc(gport->render_priv->out_pixel, lead_gc, FALSE, + Vx(lead_user->x - radius), Vy(lead_user->y - radius), Vz(2. * radius), Vz(2. * radius), 0, 360 * 64); + } +} + +void ghid_gdk_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + if (common != NULL) { + 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->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; + + hid->request_debug_draw = ghid_gdk_request_debug_draw; + hid->flush_debug_draw = ghid_gdk_flush_debug_draw; + hid->finish_debug_draw = ghid_gdk_finish_debug_draw; + } +} Index: tags/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-main.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-main.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/gtkhid-main.c (revision 13657) @@ -0,0 +1,67 @@ +#include "config.h" + +#include + +#include "action_helper.h" +#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_config/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_config/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; + +void gtk2_gdk_parse_arguments(int *argc, char ***argv) +{ + ghid_gdk_install(&ghidgui->common, NULL); + 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) +{ + 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/1.2.7/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (revision 13657) @@ -0,0 +1,11 @@ +$class hid +$short GTK2 GUI, software render +$long GUI: GTK2 HID with GDK software rendering. +$state works +default buildin +dep lib_gtk_common +dep lib_gtk_config +dep lib_gtk_hid +dep draw_csect +dep draw_fontsel +autoload 1 Index: tags/1.2.7/src_plugins/hid_gtk2_gdk/pcb.rc =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gdk/pcb.rc (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gdk/pcb.rc (revision 13657) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/1.2.7/src_plugins/hid_gtk2_gl/Makefile =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gl + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/Plug.tmpasm (revision 13657) @@ -0,0 +1,22 @@ +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 + $(PLUGDIR)/hid_gtk2_gl/hidgl.o + $(PLUGDIR)/hid_gtk2_gl/draw_gl.o + $(PLUGDIR)/hid_gtk2_gl/stencil_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/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.c (revision 13657) @@ -0,0 +1,615 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2017 PCB Contributers (See ChangeLog for details) + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include +#include +#include +#include +#include + +#include "stencil_gl.h" + +#define MARKER_STACK_SIZE 16 +#define RESERVE_VERTEX_EXTRA 1024 +#define RESERVE_PRIMITIVE_EXTRA 256 + +enum +{ + PRIM_MASK_CREATE = 1000, + PRIM_MASK_DESTROY, + PRIM_MASK_USE +}; + + +/* Vertex Buffer Data + * The vertex buffer is a dynamic array of vertices. Each vertex contains + * position and colour information. + */ + +typedef struct +{ + GLfloat x; + GLfloat y; + GLfloat r; + GLfloat g; + GLfloat b; + GLfloat a; +} vertex_t; + + +typedef struct +{ + vertex_t * data; /* A dynamic array of vertices. */ + int capacity; /* The capacity of the buffer (by number of vertices) */ + int size; /* The number of vertices in the buffer. */ + int marker; /* An index that allows vertices after the marker to be removed. */ +} vertex_buffer_t; + +static vertex_buffer_t vertex_buffer = {0}; + +/* Primitive Buffer Data */ + +typedef struct +{ + int type; /* The type of the primitive, eg. GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN */ + GLint first; /* The index of the first vertex in the vertex buffer. */ + GLsizei count; /* The number of vertices */ +} primitive_t; + +typedef struct +{ + primitive_t * data; /* A dynamic array of primitives */ + int capacity; /* The number of primitives that can fit into the primitive_data */ + int size; /* The actual number of primitives in the primitive buffer */ + int marker; /* An index that allows primitives after the marker to be removed. */ + int dirty_index; /* The index of the first primitive that hasn't been drawn yet. */ +} primitive_buffer_t; + +static primitive_buffer_t primitive_buffer = {0}; + +static GLfloat red = 0.0f; +static GLfloat green = 0.0f; +static GLfloat blue = 0.0f; +static GLfloat alpha = 0.75f; + +static int mask_stencil = 0; + +static inline void +vertex_buffer_clear() +{ + vertex_buffer.size = 0; + vertex_buffer.marker = 0; +} + +static void +vertex_buffer_destroy() +{ + vertex_buffer_clear(); + if(vertex_buffer.data) { + free(vertex_buffer.data); + vertex_buffer.data = NULL; + } +} + +/* Ensure that the total capacity of the vertex buffer is at least 'size' vertices. + * When the buffer is reallocated, extra vertices will be added to avoid many small + * allocations beingi made. + */ +static int +vertex_buffer_reserve(int size) +{ + int result = 0; + if(size > vertex_buffer.capacity) { + vertex_t * p_data = realloc(vertex_buffer.data,(size + RESERVE_VERTEX_EXTRA) * sizeof(vertex_t)); + if(p_data == NULL) + result = -1; + else { + vertex_buffer.data = p_data; + vertex_buffer.capacity = size + RESERVE_VERTEX_EXTRA; + } + } + return result; +} + +/* Ensure that the capacity of the vertex buffer can accomodate an allocation + * of at least 'size' vertices. + */ +static inline int +vertex_buffer_reserve_extra(int size) +{ + return vertex_buffer_reserve(vertex_buffer.size + size); +} + +/* Set the marker to the end of the active vertex data. This allows vertices + * added after the marker has been set to be discarded. This is required when + * temporary vertices are required to draw something that will not be required + * for the final render pass. + */ +static inline int +vertex_buffer_set_marker() +{ + vertex_buffer.marker = vertex_buffer.size; + return vertex_buffer.marker; +} + +/* Discard vertices added after the marker was set. The end of the buffer will then be + * the position of the marker. + */ +static inline void +vertex_buffer_rewind() +{ + vertex_buffer.size = vertex_buffer.marker; +} + +static inline vertex_t * +vertex_buffer_allocate(int size) +{ + vertex_t * p_vertex = NULL; + if(vertex_buffer_reserve_extra(size) == 0) { + p_vertex = &vertex_buffer.data[vertex_buffer.size]; + vertex_buffer.size += size; + } + + return p_vertex; +} + +static inline void +vertex_buffer_add(GLfloat x,GLfloat y) +{ + vertex_t * p_vert = vertex_buffer_allocate(1); + if(p_vert) { + p_vert->x = x; + p_vert->y = y; + p_vert->r = red; + p_vert->g = green; + p_vert->b = blue; + p_vert->a = alpha; + } +} + +static inline void +primitive_buffer_clear() +{ + primitive_buffer.size = 0; + primitive_buffer.dirty_index = 0; + primitive_buffer.marker = 0; +} + +static void +primitive_buffer_destroy() +{ + primitive_buffer_clear(); + if(primitive_buffer.data) { + free(primitive_buffer.data); + primitive_buffer.data = NULL; + } +} + +/* Ensure that the total capacity of the primitive buffer is at least 'size' + * primitives. When reallocating the buffer, extra primitives will be added + * to avoid many small reallocations. + */ +static int +primitive_buffer_reserve(int size) +{ + int result = 0; + + if(size > primitive_buffer.capacity) { + primitive_t * p_data = realloc(primitive_buffer.data,(size + RESERVE_PRIMITIVE_EXTRA) * sizeof(primitive_t)); + if(p_data == NULL) + result = -1; + else { + primitive_buffer.data = p_data; + primitive_buffer.capacity = size + RESERVE_PRIMITIVE_EXTRA; + } + } + + return result; +} + +/* Ensure that the capacity of the primitive buffer can accomodate an allocation + * of at least 'size' primitives. + */ +static inline int +primitive_buffer_reserve_extra(int size) +{ + return primitive_buffer_reserve(primitive_buffer.size + size); +} + +/* Set the marker to the end of the active primitive data. This allows primitives + * added after the marker to be discarded. This is required when temporary primitives + * are required to draw something that will not be required for the final render pass. + */ +static inline int +primitive_buffer_set_marker() +{ + primitive_buffer.marker = primitive_buffer.size; + return primitive_buffer.marker; +} + +/* Discard primitives added after the marker was set. The end of the buffer will then be + * the position of the marker. + */ +static inline void +primitive_buffer_rewind() +{ + primitive_buffer.size = primitive_buffer.marker; +} + +static inline primitive_t * +primitive_buffer_back() +{ + return (primitive_buffer.size > 0) && (primitive_buffer.data) ? &primitive_buffer.data[primitive_buffer.size-1] : NULL; +} + +static inline int +primitive_dirty_count() +{ + return primitive_buffer.size - primitive_buffer.dirty_index; +} + +static void +primitive_buffer_add(int type,GLint first,GLsizei count) +{ + primitive_t * last = primitive_buffer_back(); + + /* If the last primitive is the same type AND that type can be extended + * AND the last primitive is dirty AND 'first' follows the last vertex of + * the previous primitive THEN we can simply append the new primitive to + * the last one. + */ + if( last && + (primitive_dirty_count()>0) && + (last->type == type) && + ((type == GL_LINES) || (type == GL_TRIANGLES) || (type == GL_POINTS)) && + ((last->first + last->count) == first) ) + last->count += count; + else if(primitive_buffer_reserve_extra(1) == 0) { + primitive_t * p_prim = &primitive_buffer.data[primitive_buffer.size++]; + p_prim->type = type; + p_prim->first = first; + p_prim->count = count; + } +} + +static inline int +primitive_buffer_last_type() +{ + return primitive_buffer.size > 0 ? primitive_buffer.data[primitive_buffer.size-1].type : GL_ZERO; +} + +void +drawgl_set_colour(GLfloat r,GLfloat g,GLfloat b,GLfloat a) +{ + red = r; + green = g; + blue = b; + alpha = a; +} + +void +drawgl_add_triangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat x3,GLfloat y3) +{ + /* Debug Drawing + primitive_buffer_add(GL_LINES,vertex_buffer.size,6); + vertex_buffer_reserve_extra(6); + vertex_buffer_add(x1,y1); vertex_buffer_add(x2,y2); + vertex_buffer_add(x2,y2); vertex_buffer_add(x3,y3); + vertex_buffer_add(x3,y3); vertex_buffer_add(x1,y1); + */ + + primitive_buffer_add(GL_TRIANGLES,vertex_buffer.size,3); + vertex_buffer_reserve_extra(3); + vertex_buffer_add(x1,y1); + vertex_buffer_add(x2,y2); + vertex_buffer_add(x3,y3); + +} + +void +drawgl_add_line(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2) +{ + primitive_buffer_add(GL_LINES,vertex_buffer.size,2); + vertex_buffer_reserve_extra(2); + vertex_buffer_add(x1,y1); + vertex_buffer_add(x2,y2); +} + +void +drawgl_add_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2) +{ + primitive_buffer_add(GL_LINE_LOOP,vertex_buffer.size,4); + vertex_buffer_reserve_extra(4); + vertex_buffer_add(x1,y1); + vertex_buffer_add(x2,y1); + vertex_buffer_add(x2,y2); + vertex_buffer_add(x1,y2); +} + +void +drawgl_add_mask_create() +{ + primitive_buffer_add(PRIM_MASK_CREATE,0,0); +} + +void +drawgl_add_mask_destroy() +{ + primitive_buffer_add(PRIM_MASK_DESTROY,0,0); +} + +void +drawgl_add_mask_use() +{ + primitive_buffer_add(PRIM_MASK_USE,0,0); +} + +void +drawgl_direct_draw_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2) +{ + glBegin(GL_LINE_LOOP); + glColor4f(red,green,blue,alpha); + glVertex2f(x1,y1); + glVertex2f(x2,y1); + glVertex2f(x2,y2); + glVertex2f(x1,y2); + glEnd(); +} + +void +drawgl_direct_draw_solid_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2) +{ + glBegin(GL_TRIANGLES); + glColor4f(red,green,blue,alpha); + glVertex2f(x1,y1); + glVertex2f(x2,y1); + glVertex2f(x1,y2); + glVertex2f(x2,y1); + glVertex2f(x2,y2); + glVertex2f(x1,y2); + glEnd(); +} + +void +drawgl_reserve_triangles(int count) +{ + vertex_buffer_reserve_extra(count * 3); +} + +/* This function will draw the specified primitive but it may also modify the state of + * the stencil buffer when MASK primtives exist. + */ +static inline void +drawgl_draw_primtive(primitive_t * prim) +{ + switch(prim->type) { + case PRIM_MASK_CREATE : + if(mask_stencil) + stencilgl_return_stencil_bit(mask_stencil); + mask_stencil = stencilgl_allocate_clear_stencil_bit(); + if(mask_stencil != 0) { + glPushAttrib(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + glStencilMask(mask_stencil); + glStencilFunc(GL_ALWAYS,mask_stencil,mask_stencil); + glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); + glColorMask(0,0,0,0); + } + break; + + case PRIM_MASK_USE : + { + GLint ref = 0; + glPopAttrib(); + glPushAttrib(GL_STENCIL_BUFFER_BIT); + glGetIntegerv(GL_STENCIL_REF,&ref); + glStencilFunc(GL_GEQUAL,ref & ~mask_stencil,mask_stencil); + } + break; + + case PRIM_MASK_DESTROY : + glPopAttrib(); + stencilgl_return_stencil_bit(mask_stencil); + mask_stencil = 0; + break; + + default : + glDrawArrays(prim->type, prim->first, prim->count); + break; + } +} + +void +drawgl_flush() +{ + int index = primitive_buffer.dirty_index; + int end = primitive_buffer.size; + primitive_t * prim = &primitive_buffer.data[index]; + + /* Setup the vertex buffer */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(2, GL_FLOAT, sizeof(vertex_t), &vertex_buffer.data[0].x); + glColorPointer(4, GL_FLOAT, sizeof(vertex_t), &vertex_buffer.data[0].r); + + /* draw the primitives */ + while(index < end) { + drawgl_draw_primtive(prim); + ++prim; + ++index; + } + + /* disable the vertex buffer */ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + primitive_buffer.dirty_index = end; +} + +/* Draw all buffered primitives. The dirty index is ignored and will remain unchanged. + * This function accepts stencil bits that can be used to mask the drawing. + */ +void +drawgl_draw_all(int stencil_bits) +{ + int index = primitive_buffer.size; + primitive_t * prim; + int mask = 0; + + if((index == 0) || (primitive_buffer.data == NULL)) + return; + + --index; + prim = &primitive_buffer.data[index]; + + /* Setup the vertex buffer */ + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glVertexPointer(2, GL_FLOAT, sizeof(vertex_t), &vertex_buffer.data[0].x); + glColorPointer(4, GL_FLOAT, sizeof(vertex_t), &vertex_buffer.data[0].r); + + /* draw the primitives */ + while(index >= 0) { + switch(prim->type) { + case PRIM_MASK_DESTROY : + /* The primitives are drawn in reverse order. The mask primitives are required + * to be processed in forward order so we must search for the matching 'mask create' + * primitive and then iterate through the primtives until we reach the 'mask destroy' + * primitive. + */ + { + primitive_t * next_prim = prim-1;; + primitive_t * mask_prim = prim; + int mask_index = index; + int next_index = index-1; + + /* Find the 'mask create' primitive. */ + while((mask_index>=0) && (mask_prim->type != PRIM_MASK_CREATE)) { + --mask_prim; + --mask_index; + } + + /* Process the primitives in forward order until we reach the 'mask destroy' primitive */ + if(mask_prim->type == PRIM_MASK_CREATE) { + next_index = mask_index; + next_prim = mask_prim; + + while(mask_index <= index) { + switch(mask_prim->type) { + case PRIM_MASK_CREATE : + if(mask) + stencilgl_return_stencil_bit(mask); + mask = stencilgl_allocate_clear_stencil_bit(); + + if(mask != 0) { + glPushAttrib(GL_STENCIL_BUFFER_BIT); + + glEnable(GL_STENCIL_TEST); + stencilgl_mode_write_set(mask); + } + glPushAttrib(GL_COLOR_BUFFER_BIT); + glColorMask(0,0,0,0); + break; + + case PRIM_MASK_USE : + glPopAttrib(); + if(mask != 0) { + glEnable(GL_STENCIL_TEST); + glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO); + glStencilFunc(GL_EQUAL,stencil_bits , stencil_bits | mask ); + glStencilMask(stencil_bits); + } + break; + + case PRIM_MASK_DESTROY : + if(mask != 0) { + glPopAttrib(); + stencilgl_return_stencil_bit(mask); + mask = 0; + } + break; + + default : + glDrawArrays(mask_prim->type, mask_prim->first, mask_prim->count); + break; + } + ++mask_prim; + ++mask_index; + } + + index = next_index; + prim = next_prim; + } + else { + index = mask_index; + prim = mask_prim; + } + } + break; + + default : + glDrawArrays(prim->type, prim->first, prim->count); + break; + } + + --prim; + --index; + } + + if(mask) + stencilgl_return_stencil_bit(mask); + + /* disable the vertex buffer */ + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + +} + +void +drawgl_reset() +{ + vertex_buffer_clear(); + primitive_buffer_clear(); +} + +void +drawgl_set_marker() +{ + vertex_buffer_set_marker(); + primitive_buffer_set_marker(); +} + +void +drawgl_rewind_to_marker() +{ + vertex_buffer_rewind(); + primitive_buffer_rewind(); +} + +void +drawgl_uninit() +{ + vertex_buffer_destroy(); + primitive_buffer_destroy(); +} + + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.h =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.h (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/draw_gl.h (revision 13657) @@ -0,0 +1,53 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2017 PCB Contributers (See ChangeLog for details) + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +#ifndef HID_GTK2_GL_DRAW_GL_H +#define HID_GTK2_GL_DRAW_GL_H + +#include "config.h" +#include "opengl.h" + +void drawgl_uninit(); + +void drawgl_reserve_triangles(int count); + +void drawgl_set_colour(GLfloat r,GLfloat g,GLfloat b,GLfloat a); + +void drawgl_add_triangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2,GLfloat x3,GLfloat y3); +void drawgl_add_line(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2); +void drawgl_add_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2); +void drawgl_add_mask_create(); +void drawgl_add_mask_destroy(); +void drawgl_add_mask_use(); + +void drawgl_flush(); +void drawgl_reset(); +void drawgl_draw_all(int stencil_bits); + +void drawgl_direct_draw_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2); +void drawgl_direct_draw_solid_rectangle(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2); + +void drawgl_set_marker(); +void drawgl_rewind_to_marker(); + +#endif /* ! defined HID_GTK2_GL_DRAW_GL_H */ + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-gl.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-gl.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-gl.c (revision 13657) @@ -0,0 +1,1214 @@ +#include "config.h" + +#include + +#include "crosshair.h" +#include "clip.h" +#include "data.h" +#include "layer.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "hid_color.h" + +#include "../src_plugins/lib_gtk_config/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_config/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 "opengl.h" +#include +#include "draw_gl.h" +#include "hidgl.h" +#include "hid_draw_helpers.h" +#include "stencil_gl.h" + +#include "../src_plugins/lib_gtk_config/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; + GdkColor bg_color; + GdkColor offlimits_color; + GdkColor 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_hid_t *me_pointer; + + const char *colorname; + double alpha_mult; + pcb_coord_t width; + gint cap, join; + gchar xor; +} hid_gc_s; + +static void draw_lead_user(render_priv_t * priv); + +void ghid_gl_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ + +} + +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 \p color_string has been allocated to \p 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 geoemtry 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 geoemtry 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, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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 /*&& !pinout */ ); + } + + /* 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; + } + + /* virtual layers */ + { + 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_ASSY: + return 0; + case PCB_LYT_PDRILL: + case PCB_LYT_UDRILL: + return 1; + case PCB_LYT_RAT: + return PCB->RatOn; + case PCB_LYT_CSECT: + /* 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; + } + } + 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->colorname = 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); +} + +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 proabbly determine what the maxmimum 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); + } + + 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); +} + + /* 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, int arr_idx) +{ + 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], &priv->bg_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/background"), -1); + set_special_grid_color(); + } + } + else if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.off_limit)) { + if (map_color_string(cfg->val.color[0], &priv->offlimits_color)) + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/off_limit"), -1); + } + else if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.grid)) { + if (map_color_string(cfg->val.color[0], &priv->grid_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/grid"), -1); + set_special_grid_color(); + } + } +} + +typedef struct { + int color_set; + GdkColor color; + int xor_set; + GdkColor 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 (priv->current_colorname != NULL && + strcmp(priv->current_colorname, gc->colorname) == 0 && priv->current_alpha_mult == gc->alpha_mult) + return; + + free(priv->current_colorname); + priv->current_colorname = pcb_strdup(gc->colorname); + priv->current_alpha_mult = gc->alpha_mult; + + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + if (strcmp(gc->colorname, "erase") == 0) { + r = priv->bg_color.red / 65535.; + g = priv->bg_color.green / 65535.; + b = priv->bg_color.blue / 65535.; + a = 1.0; + } + else if (strcmp(gc->colorname, "drill") == 0) { + 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->colorname, &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->colorname, &cval, &cache); + } + + if (!cc->color_set) { + if (gdk_color_parse(gc->colorname, &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 primtives + * 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 primtive 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 char *name) +{ + gc->colorname = name; + 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) +{ + gc->cap = 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; +} + + +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->cap, gc->width, x1, y1, x2, y2, gport->view.coord_per_px); +} + +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); +} + +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); + + drawgl_add_rectangle(x1, y1, x2, y2); +} + + +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); +} + + +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); +} + +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); +} + +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); +} + +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); + */ +} + +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(); +} + +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(); +} + +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 draw_right_cross(gint x, gint y, gint z) +{ + glVertex3i(x, 0, z); + glVertex3i(x, PCB->MaxHeight, z); + glVertex3i(0, y, z); + glVertex3i(PCB->MaxWidth, y, z); +} + +static void draw_slanted_cross(gint x, gint y, gint z) +{ + gint 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 draw_dozen_cross(gint x, gint y, gint z) +{ + gint 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); +} + +static void draw_crosshair(gint x, gint y, gint z) +{ + static enum pcb_crosshair_shape_e prev = pcb_ch_shape_basic; + + draw_right_cross(x, y, z); + if (prev == pcb_ch_shape_union_jack) + draw_slanted_cross(x, y, z); + if (prev == pcb_ch_shape_dozen) + draw_dozen_cross(x, y, z); + prev = pcb_crosshair.shape; +} + +void ghid_gl_show_crosshair(gboolean paint_new_location) +{ + gint x, y, z; + static int done_once = 0; + static GdkColor 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, &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); + draw_crosshair(x, y, z); + glEnd(); + } + + glDisable(GL_COLOR_LOGIC_OP); +} + +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; +} + +void ghid_gl_shutdown_renderer(void * p) +{ + GHidPort *port = p; + + g_free(port->render_priv); + port->render_priv = NULL; +} + +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); +} + +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, &priv->bg_color)) + map_color_string("white", &priv->bg_color); + + if (!map_color_string(conf_core.appearance.color.off_limit, &priv->offlimits_color)) + map_color_string("white", &priv->offlimits_color); + + if (!map_color_string(conf_core.appearance.color.grid, &priv->grid_color)) + map_color_string("blue", &priv->grid_color); + set_special_grid_color(); + + done_once = 1; + } +} + +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; +} + +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); +} + +void ghid_gl_screen_update(void) +{ +} + +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; + + gtk_widget_get_allocation(widget, &allocation); + + ghid_gl_start_drawing(port); + + 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) + gtk2_gl_hid.fill_pcb_polygon = pcb_dhlp_fill_pcb_polygon; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, allocation.width, allocation.height); + + glEnable(GL_SCISSOR_TEST); + glScissor(ev->area.x, allocation.height - ev->area.height - ev->area.y, ev->area.width, ev->area.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, allocation.width, allocation.height, 0, 0, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + + 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); + + glEnable(GL_STENCIL_TEST); + glClearColor(priv->offlimits_color.red / 65535., + priv->offlimits_color.green / 65535., priv->offlimits_color.blue / 65535., 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); + + 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)); + + glColor3f(priv->bg_color.red / 65535., priv->bg_color.green / 65535., priv->bg_color.blue / 65535.); + + 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); + drawgl_flush(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + + ghid_gl_draw_grid(&ctx.view); + + ghid_gl_invalidate_current_gc(); + + pcb_draw_attached(); + pcb_draw_mark(); + drawgl_flush(); + + ghid_gl_show_crosshair(TRUE); + + drawgl_flush(); + + draw_lead_user(priv); + + 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. + */ +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; +} + +gboolean ghid_gl_preview_expose(GtkWidget * widget, pcb_gtk_expose_t *ev, pcb_hid_expose_t expcall, const 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; + + 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; + + /* make GL-context "current" */ + if (!gdk_gl_drawable_gl_begin(pGlDrawable, pGlContext)) { + return FALSE; + } + gport->render_priv->in_context = pcb_true; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, allocation.width, allocation.height); + + glEnable(GL_SCISSOR_TEST); + if (ev) + glScissor(ev->area.x, allocation.height - ev->area.height - ev->area.y, ev->area.width, ev->area.height); + else + glScissor(0, 0, allocation.width, allocation.height); + + 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(priv->bg_color.red / 65535., priv->bg_color.green / 65535., priv->bg_color.blue / 65535., 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); + + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +pcb_hid_t *ghid_gl_request_debug_draw(void) +{ + GHidPort *port = gport; + GtkWidget *widget = port->drawing_area; + GtkAllocation allocation; + + gtk_widget_get_allocation(widget, &allocation); + + ghid_gl_start_drawing(port); + + glViewport(0, 0, allocation.width, allocation.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, allocation.width, allocation.height, 0, 0, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + +/* hidgl_init_triangle_array(&buffer);*/ + ghid_gl_invalidate_current_gc(); + + /* Setup stenciling */ + glDisable(GL_STENCIL_TEST); + + glPushMatrix(); + 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.); + 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); + + return >k2_gl_hid; +} + +void ghid_gl_flush_debug_draw(void) +{ + GtkWidget *widget = gport->drawing_area; + GdkGLDrawable *pGlDrawable = gtk_widget_get_gl_drawable(widget); + + drawgl_flush(); + + if (gdk_gl_drawable_is_double_buffered(pGlDrawable)) + gdk_gl_drawable_swap_buffers(pGlDrawable); + else + glFlush(); +} + +void ghid_gl_finish_debug_draw(void) +{ + drawgl_flush(); + glPopMatrix(); + + ghid_gl_end_drawing(gport); +} + +static void draw_lead_user(render_priv_t * priv) +{ + int i; + pcb_lead_user_t *lead_user = &gport->lead_user; + double radius = lead_user->radius; + double width = PCB_MM_TO_COORD(LEAD_USER_WIDTH); + double separation = PCB_MM_TO_COORD(LEAD_USER_ARC_SEPARATION); + + if (!lead_user->lead_user) + return; + + glPushAttrib(GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT); + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(GL_XOR); + glColor3f(LEAD_USER_COLOR_R, LEAD_USER_COLOR_G, LEAD_USER_COLOR_B); + + + /* arcs at the approrpriate radii */ + + for (i = 0; i < LEAD_USER_ARC_COUNT; i++, radius -= separation) { + if (radius < width) + radius += PCB_MM_TO_COORD(LEAD_USER_INITIAL_RADIUS); + + /* Draw an arc at radius */ + hidgl_draw_arc(width, lead_user->x, lead_user->y, radius, radius, 0, 360, gport->view.coord_per_px); + } + + drawgl_flush(); + glPopAttrib(); +} + + + + +void ghid_gl_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + + if (common != NULL) { + 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; + + hid->request_debug_draw = ghid_gl_request_debug_draw; + hid->flush_debug_draw = ghid_gl_flush_debug_draw; + hid->finish_debug_draw = ghid_gl_finish_debug_draw; + + hid->holes_after = 1; + } +} + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-main.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-main.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/gtkhid-main.c (revision 13657) @@ -0,0 +1,69 @@ +#include "config.h" + +#include + +#include "action_helper.h" +#include "error.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_init.h" +#include "conf_core.h" +#include "draw_gl.h" + +#include "../src_plugins/lib_gtk_common/glue.h" +#include "../src_plugins/lib_gtk_config/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_config/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; + +void gtk2_gl_parse_arguments(int *argc, char ***argv) +{ + ghid_gl_install(&ghidgui->common, NULL); + 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) +{ + 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/1.2.7/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (revision 13657) @@ -0,0 +1,11 @@ +$class hid +$short GTK2 GUI, opengl render +$long GUI: GTK2 with opengl rendering +$state works +default buildin +dep lib_gtk_common +dep lib_gtk_config +dep lib_gtk_hid +dep draw_csect +dep draw_fontsel +autoload 1 Index: tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.c (revision 13657) @@ -0,0 +1,766 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2011 PCB Contributers (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. + * + */ + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "crosshair.h" +#include "clip.h" +#include "data.h" +#include "layer.h" +#include "board.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "hid_color.h" + +#include "../src_plugins/lib_gtk_config/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_config/lib_gtk_config.h" + +#include "opengl.h" + +#include "action_helper.h" +#include "crosshair.h" +#include "data.h" +#include "error.h" +#include "clip.h" + +#include "hid.h" +#include "hidgl.h" +#include "rtree.h" +#include "stencil_gl.h" + +void hidgl_init(void) +{ + stencilgl_init(); +} + +static pcb_composite_op_t composite_op = PCB_HID_COMP_RESET; +static pcb_bool direct_mode = pcb_true; +static int comp_stencil_bit = 0; + +static GLfloat * grid_points = NULL; +static int grid_point_capacity = 0; + + +static inline void +mode_reset(pcb_bool direct,const pcb_box_t * screen) +{ + drawgl_flush(); + drawgl_reset(); + glColorMask(0, 0, 0, 0); /* Disable colour drawing */ + stencilgl_reset_stencil_usage(); + comp_stencil_bit = 0; +} + +static inline void +mode_positive(pcb_bool direct,const pcb_box_t * screen) +{ + if(comp_stencil_bit == 0) + comp_stencil_bit = stencilgl_allocate_clear_stencil_bit(); + else + drawgl_flush(); + + glEnable(GL_STENCIL_TEST); + stencilgl_mode_write_set(comp_stencil_bit); +} + +static inline void +mode_negative(pcb_bool direct,const pcb_box_t * screen) +{ + glEnable(GL_STENCIL_TEST); + + if(comp_stencil_bit == 0) { + /* The stencil isn't valid yet which means that this is the first pos/neg mode + * set since the reset. The compositing stencil bit will be allocated. Because + * this is a negative mode and it's the first mode to be set, the stencil buffer + * will be set to all ones. + */ + comp_stencil_bit = stencilgl_allocate_clear_stencil_bit(); + stencilgl_mode_write_set(comp_stencil_bit); + drawgl_direct_draw_solid_rectangle(screen->X1,screen->Y1,screen->X2,screen->Y2); + } + else + drawgl_flush(); + + stencilgl_mode_write_clear(comp_stencil_bit); + drawgl_set_marker(); +} + +static inline void +mode_flush(pcb_bool direct,const pcb_box_t * screen) +{ + drawgl_flush(); + glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); + + if(comp_stencil_bit) { + glEnable(GL_STENCIL_TEST); + + /* Setup the stencil to allow writes to the colour buffer if the + * comp_stencil_bit is set. After the operation, the comp_stencil_bit + * will be cleared so that any further writes to this pixel are disabled. + */ + glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO); + glStencilMask(comp_stencil_bit); + glStencilFunc(GL_EQUAL, comp_stencil_bit, comp_stencil_bit); + + /* Draw all primtives through the stencil to the colour buffer. */ + drawgl_draw_all(comp_stencil_bit); + + } + + glDisable(GL_STENCIL_TEST); + stencilgl_reset_stencil_usage(); + comp_stencil_bit = 0; +} + + +void +hidgl_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t * screen) +{ + /* If the previous mode was NEGATIVE then all of the primitives drawn + * in that mode were used only for creating the stencil and will not be + * drawn directly to the colour buffer. Therefore these primitives can be + * discarded by rewinding the primitive buffer to the marker that was + * set when entering NEGATIVE mode. + */ + if(composite_op == PCB_HID_COMP_NEGATIVE) { + drawgl_flush(); + drawgl_rewind_to_marker(); + } + + composite_op = op; + direct_mode = direct; + + switch(op) { + case PCB_HID_COMP_RESET : mode_reset(direct,screen); break; + case PCB_HID_COMP_POSITIVE : mode_positive(direct,screen); break; + case PCB_HID_COMP_NEGATIVE : mode_negative(direct,screen); break; + case PCB_HID_COMP_FLUSH : mode_flush(direct,screen); break; + default : break; + } + +} + + +void hidgl_fill_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + drawgl_add_triangle(x1, y1, x1, y2, x2, y2); + drawgl_add_triangle(x2, y1, x2, y2, x1, y1); +} + + +static inline void reserve_grid_points(int n) +{ + if (n > grid_point_capacity) { + grid_point_capacity = n + 10; + grid_points = realloc(grid_points, grid_point_capacity * 2 * sizeof(GLfloat)); + } +} + +void hidgl_draw_local_grid(pcb_coord_t cx,pcb_coord_t cy,int radius) +{ + int npoints = 0; + pcb_coord_t x,y; + + /* PI is approximated with 3.25 here - allows a minimal overallocation, speeds up calculations */ + const int r2 = radius * radius; + const int n = r2 * 3 + r2 / 4 + 1; + + reserve_grid_points(n); + + for(y = -radius; y <= radius; y++) { + int y2 = y*y; + for(x = -radius; x <= radius; x++) { + if (x*x + y2 < r2) { + grid_points[npoints*2] = x*PCB->Grid + cx; + grid_points[npoints*2+1] = y*PCB->Grid + cy; + npoints++; + } + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, grid_points); + glDrawArrays(GL_POINTS, 0, npoints); + glDisableClientState(GL_VERTEX_ARRAY); + +} + +void hidgl_draw_grid(pcb_box_t * drawn_area) +{ + pcb_coord_t x1, y1, x2, y2, n, i; + double x, y; + + x1 = pcb_grid_fit(MAX(0, drawn_area->X1), PCB->Grid, PCB->GridOffsetX); + y1 = pcb_grid_fit(MAX(0, drawn_area->Y1), PCB->Grid, PCB->GridOffsetY); + x2 = pcb_grid_fit(MIN(PCB->MaxWidth, drawn_area->X2), PCB->Grid, PCB->GridOffsetX); + y2 = pcb_grid_fit(MIN(PCB->MaxHeight, drawn_area->Y2), PCB->Grid, PCB->GridOffsetY); + + if (x1 > x2) { + pcb_coord_t tmp = x1; + x1 = x2; + x2 = tmp; + } + + if (y1 > y2) { + pcb_coord_t tmp = y1; + y1 = y2; + y2 = tmp; + } + + n = (int) ((x2 - x1) / PCB->Grid + 0.5) + 1; + reserve_grid_points(n); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, grid_points); + + n = 0; + for (x = x1; x <= x2; x += PCB->Grid, ++n) + grid_points[2 * n + 0] = x; + + for (y = y1; y <= y2; y += PCB->Grid) { + for (i = 0; i < n; i++) + grid_points[2 * i + 1] = y; + glDrawArrays(GL_POINTS, 0, n); + } + + glDisableClientState(GL_VERTEX_ARRAY); +} + +#define MAX_PIXELS_ARC_TO_CHORD 0.5 +#define MIN_SLICES 6 +int calc_slices(float pix_radius, float sweep_angle) +{ + float slices; + + if (pix_radius <= MAX_PIXELS_ARC_TO_CHORD) + return MIN_SLICES; + + slices = sweep_angle / acosf(1 - MAX_PIXELS_ARC_TO_CHORD / pix_radius) / 2.; + return (int) ceilf(slices); +} + +#define MIN_TRIANGLES_PER_CAP 3 +#define MAX_TRIANGLES_PER_CAP 90 +static void draw_cap(pcb_coord_t width, pcb_coord_t x, pcb_coord_t y, pcb_angle_t angle, double scale) +{ + float last_capx, last_capy; + float capx, capy; + float radius = width / 2.; + int slices = calc_slices(radius / scale, M_PI); + int i; + + if (slices < MIN_TRIANGLES_PER_CAP) + slices = MIN_TRIANGLES_PER_CAP; + + if (slices > MAX_TRIANGLES_PER_CAP) + slices = MAX_TRIANGLES_PER_CAP; + + drawgl_reserve_triangles(slices); + + last_capx = radius * cosf(angle * M_PI / 180.) + x; + last_capy = -radius * sinf(angle * M_PI / 180.) + y; + for (i = 0; i < slices; i++) { + capx = radius * cosf(angle * M_PI / 180. + ((float) (i + 1)) * M_PI / (float) slices) + x; + capy = -radius * sinf(angle * M_PI / 180. + ((float) (i + 1)) * M_PI / (float) slices) + y; + drawgl_add_triangle(last_capx,last_capy,capx,capy,x,y); + last_capx = capx; + last_capy = capy; + } +} + +void hidgl_draw_line(int cap, pcb_coord_t width, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, double scale) +{ + double angle; + float deltax, deltay, length; + float wdx, wdy; + int circular_caps = 0; + + if (width == 0) + drawgl_add_line(x1,y1,x2,y2); + else { + if (width < scale) + width = scale; + + deltax = x2 - x1; + deltay = y2 - y1; + + length = sqrt(deltax * deltax + deltay * deltay); + + if (length == 0) { + /* Assume the orientation of the line is horizontal */ + angle = 0; + wdx = 0; + wdy = width / 2.; + length = 1.; + deltax = 1.; + deltay = 0.; + } + else { + wdy = deltax * width / 2. / length; + wdx = -deltay * width / 2. / length; + + if (deltay == 0.) + angle = (deltax < 0) ? 270. : 90.; + else + angle = 180. / M_PI * atanl(deltax / deltay); + + if (deltay < 0) + angle += 180.; + } + + switch (cap) { + case Trace_Cap: + case Round_Cap: + circular_caps = 1; + break; + + case Square_Cap: + case Beveled_Cap: + x1 -= deltax * width / 2. / length; + y1 -= deltay * width / 2. / length; + x2 += deltax * width / 2. / length; + y2 += deltay * width / 2. / length; + break; + } + + drawgl_add_triangle(x1 - wdx, y1 - wdy, x2 - wdx, y2 - wdy, x2 + wdx, y2 + wdy); + drawgl_add_triangle(x1 - wdx, y1 - wdy, x2 + wdx, y2 + wdy, x1 + wdx, y1 + wdy); + + if (circular_caps) { + draw_cap(width, x1, y1, angle, scale); + draw_cap(width, x2, y2, angle + 180., scale); + } + } +} + +#define MIN_SLICES_PER_ARC 6 +#define MAX_SLICES_PER_ARC 360 +void hidgl_draw_arc(pcb_coord_t width, pcb_coord_t x, pcb_coord_t y, pcb_coord_t rx, pcb_coord_t ry, pcb_angle_t start_angle, pcb_angle_t delta_angle, double scale) +{ + float last_inner_x, last_inner_y; + float last_outer_x, last_outer_y; + float inner_x, inner_y; + float outer_x, outer_y; + float inner_r; + float outer_r; + float cos_ang, sin_ang; + float start_angle_rad; + float delta_angle_rad; + float angle_incr_rad; + int slices; + int i; + int hairline = 0; + + /* TODO: Draw hairlines as lines instead of triangles ? */ + + if (width == 0.0) + hairline = 1; + + if (width < scale) + width = scale; + + inner_r = rx - width / 2.; + outer_r = rx + width / 2.; + + if (delta_angle < 0) { + start_angle += delta_angle; + delta_angle = -delta_angle; + } + + start_angle_rad = start_angle * M_PI / 180.; + delta_angle_rad = delta_angle * M_PI / 180.; + + slices = calc_slices((rx + width / 2.) / scale, delta_angle_rad); + + if (slices < MIN_SLICES_PER_ARC) + slices = MIN_SLICES_PER_ARC; + + if (slices > MAX_SLICES_PER_ARC) + slices = MAX_SLICES_PER_ARC; + + drawgl_reserve_triangles(2 * slices); + + angle_incr_rad = delta_angle_rad / (float) slices; + + cos_ang = cosf(start_angle_rad); + sin_ang = sinf(start_angle_rad); + last_inner_x = -inner_r * cos_ang + x; + last_inner_y = inner_r * sin_ang + y; + last_outer_x = -outer_r * cos_ang + x; + last_outer_y = outer_r * sin_ang + y; + for (i = 1; i <= slices; i++) { + cos_ang = cosf(start_angle_rad + ((float) (i)) * angle_incr_rad); + sin_ang = sinf(start_angle_rad + ((float) (i)) * angle_incr_rad); + inner_x = -inner_r * cos_ang + x; + inner_y = inner_r * sin_ang + y; + outer_x = -outer_r * cos_ang + x; + outer_y = outer_r * sin_ang + y; + + drawgl_add_triangle( last_inner_x, last_inner_y, last_outer_x, last_outer_y, outer_x, outer_y); + drawgl_add_triangle( last_inner_x, last_inner_y, inner_x, inner_y, outer_x, outer_y); + + last_inner_x = inner_x; + last_inner_y = inner_y; + last_outer_x = outer_x; + last_outer_y = outer_y; + } + + /* Don't bother capping hairlines */ + if (hairline) + return; + + draw_cap(width, x + rx * -cosf(start_angle_rad), y + rx * sinf(start_angle_rad), start_angle, scale); + draw_cap(width, x + rx * -cosf(start_angle_rad + delta_angle_rad), + y + rx * sinf(start_angle_rad + delta_angle_rad), start_angle + delta_angle + 180., scale); +} + +void hidgl_fill_circle(pcb_coord_t vx, pcb_coord_t vy, pcb_coord_t vr, double scale) +{ +#define MIN_TRIANGLES_PER_CIRCLE 6 +#define MAX_TRIANGLES_PER_CIRCLE 360 + + float last_x, last_y; + float radius = vr; + int slices; + int i; + + assert((composite_op == PCB_HID_COMP_POSITIVE) || (composite_op == PCB_HID_COMP_NEGATIVE)); + + slices = calc_slices(vr / scale, 2 * M_PI); + + if (slices < MIN_TRIANGLES_PER_CIRCLE) + slices = MIN_TRIANGLES_PER_CIRCLE; + + if (slices > MAX_TRIANGLES_PER_CIRCLE) + slices = MAX_TRIANGLES_PER_CIRCLE; + + drawgl_reserve_triangles(slices); + + last_x = vx + vr; + last_y = vy; + + for (i = 0; i < slices; i++) { + float x, y; + x = radius * cosf(((float) (i + 1)) * 2. * M_PI / (float) slices) + vx; + y = radius * sinf(((float) (i + 1)) * 2. * M_PI / (float) slices) + vy; + drawgl_add_triangle(vx, vy, last_x, last_y, x, y); + last_x = x; + last_y = y; + } +} + + +#define MAX_COMBINED_MALLOCS 2500 +static void *combined_to_free[MAX_COMBINED_MALLOCS]; +static int combined_num_to_free = 0; + +static GLenum tessVertexType; +static int stashed_vertices; +static int triangle_comp_idx; + +static void myError(GLenum errno) +{ + printf("gluTess error: %s\n", gluErrorString(errno)); +} + +static void myFreeCombined() +{ + while (combined_num_to_free) + free(combined_to_free[--combined_num_to_free]); +} + +static void myCombine(GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **dataOut) +{ +#define MAX_COMBINED_VERTICES 2500 + static GLdouble combined_vertices[3 * MAX_COMBINED_VERTICES]; + static int num_combined_vertices = 0; + + GLdouble *new_vertex; + + if (num_combined_vertices < MAX_COMBINED_VERTICES) { + new_vertex = &combined_vertices[3 * num_combined_vertices]; + num_combined_vertices++; + } + else { + new_vertex = malloc(3 * sizeof(GLdouble)); + + if (combined_num_to_free < MAX_COMBINED_MALLOCS) + combined_to_free[combined_num_to_free++] = new_vertex; + else + printf("myCombine leaking %lu bytes of memory\n", 3 * sizeof(GLdouble)); + } + + new_vertex[0] = coords[0]; + new_vertex[1] = coords[1]; + new_vertex[2] = coords[2]; + + *dataOut = new_vertex; +} + +static void myBegin(GLenum type) +{ + tessVertexType = type; + stashed_vertices = 0; + triangle_comp_idx = 0; +} + +static double global_scale; + +static void myVertex(GLdouble * vertex_data) +{ + static GLfloat triangle_vertices[2 * 3]; + + if (tessVertexType == GL_TRIANGLE_STRIP || tessVertexType == GL_TRIANGLE_FAN) { + if (stashed_vertices < 2) { + triangle_vertices[triangle_comp_idx++] = vertex_data[0]; + triangle_vertices[triangle_comp_idx++] = vertex_data[1]; + stashed_vertices++; + } + else { + drawgl_add_triangle(triangle_vertices[0], triangle_vertices[1], + triangle_vertices[2], triangle_vertices[3], vertex_data[0], vertex_data[1]); + if (tessVertexType == GL_TRIANGLE_STRIP) { + /* STRIP saves the last two vertices for re-use in the next triangle */ + triangle_vertices[0] = triangle_vertices[2]; + triangle_vertices[1] = triangle_vertices[3]; + } + /* Both FAN and STRIP save the last vertex for re-use in the next triangle */ + triangle_vertices[2] = vertex_data[0]; + triangle_vertices[3] = vertex_data[1]; + } + } + else if (tessVertexType == GL_TRIANGLES) { + triangle_vertices[triangle_comp_idx++] = vertex_data[0]; + triangle_vertices[triangle_comp_idx++] = vertex_data[1]; + stashed_vertices++; + if (stashed_vertices == 3) { + drawgl_add_triangle(triangle_vertices[0], triangle_vertices[1], + triangle_vertices[2], triangle_vertices[3], triangle_vertices[4], triangle_vertices[5]); + triangle_comp_idx = 0; + stashed_vertices = 0; + } + } + else + printf("Vertex received with unknown type\n"); +} + +/* Intentaional code duplication for performance */ +void hidgl_fill_polygon(int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + int i; + GLUtesselator *tobj; + GLdouble *vertices; + + assert(n_coords > 0); + + vertices = malloc(sizeof(GLdouble) * n_coords * 3); + + tobj = gluNewTess(); + gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr) myBegin); + gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr) myVertex); + gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr) myCombine); + gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr) myError); + + gluTessBeginPolygon(tobj, NULL); + gluTessBeginContour(tobj); + + for (i = 0; i < n_coords; i++) { + vertices[0 + i * 3] = x[i]; + vertices[1 + i * 3] = y[i]; + vertices[2 + i * 3] = 0.; + gluTessVertex(tobj, &vertices[i * 3], &vertices[i * 3]); + } + + gluTessEndContour(tobj); + gluTessEndPolygon(tobj); + gluDeleteTess(tobj); + + myFreeCombined(); + free(vertices); +} + +/* Intentaional code duplication for performance */ +void hidgl_fill_polygon_offs(int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy) +{ + int i; + GLUtesselator *tobj; + GLdouble *vertices; + + assert(n_coords > 0); + + vertices = malloc(sizeof(GLdouble) * n_coords * 3); + + tobj = gluNewTess(); + gluTessCallback(tobj, GLU_TESS_BEGIN, (_GLUfuncptr) myBegin); + gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr) myVertex); + gluTessCallback(tobj, GLU_TESS_COMBINE, (_GLUfuncptr) myCombine); + gluTessCallback(tobj, GLU_TESS_ERROR, (_GLUfuncptr) myError); + + gluTessBeginPolygon(tobj, NULL); + gluTessBeginContour(tobj); + + for (i = 0; i < n_coords; i++) { + vertices[0 + i * 3] = x[i] + dx; + vertices[1 + i * 3] = y[i] + dy; + vertices[2 + i * 3] = 0.; + gluTessVertex(tobj, &vertices[i * 3], &vertices[i * 3]); + } + + gluTessEndContour(tobj); + gluTessEndPolygon(tobj); + gluDeleteTess(tobj); + + myFreeCombined(); + free(vertices); +} + +void tesselate_contour(GLUtesselator * tobj, pcb_pline_t * contour, GLdouble * vertices, double scale) +{ + pcb_vnode_t *vn = &contour->head; + int offset = 0; + + /* If the contour is round, and hidgl_fill_circle would use + * less slices than we have vertices to draw it, then call + * hidgl_fill_circle to draw this contour. + */ + if (contour->is_round) { + double slices = calc_slices(contour->radius / scale, 2 * M_PI); + if (slices < contour->Count) { + hidgl_fill_circle(contour->cx, contour->cy, contour->radius, scale); + return; + } + } + + gluTessBeginPolygon(tobj, NULL); + gluTessBeginContour(tobj); + do { + vertices[0 + offset] = vn->point[0]; + vertices[1 + offset] = vn->point[1]; + vertices[2 + offset] = 0.; + gluTessVertex(tobj, &vertices[offset], &vertices[offset]); + offset += 3; + } while ((vn = vn->next) != &contour->head); + gluTessEndContour(tobj); + gluTessEndPolygon(tobj); + +} + +struct do_hole_info { + GLUtesselator *tobj; + GLdouble *vertices; + double scale; +}; + +static pcb_r_dir_t do_hole(const pcb_box_t * b, void *cl) +{ + struct do_hole_info *info = cl; + pcb_pline_t *curc = (pcb_pline_t *) b; + + /* Ignore the outer contour - we draw it first explicitly */ + if (curc->Flags.orient == PCB_PLF_DIR) { + return PCB_R_DIR_NOT_FOUND; + } + + tesselate_contour(info->tobj, curc, info->vertices, info->scale); + return PCB_R_DIR_FOUND_CONTINUE; +} + + +void hidgl_fill_pcb_polygon(pcb_poly_t * poly, const pcb_box_t * clip_box, double scale) +{ + int vertex_count = 0; + pcb_pline_t *contour; + struct do_hole_info info; + pcb_polyarea_t * p_area; + const int fullpoly = PCB_FLAG_TEST(PCB_FLAG_FULLPOLY, poly); + + info.scale = scale; + global_scale = scale; + + if (poly->Clipped == NULL) { + fprintf(stderr, "hidgl_fill_pcb_polygon: poly->Clipped == NULL\n"); + return; + } + + drawgl_flush(); + + /* Walk the polygon structure, counting vertices */ + /* This gives an upper bound on the amount of storage required */ + p_area = poly->Clipped; + do { + for (contour = p_area->contours; contour != NULL; contour = contour->next) + vertex_count = MAX(vertex_count, contour->Count); + p_area = p_area->f; + } while (fullpoly && (p_area != poly->Clipped)); + + /* Allocate a vertex buffer */ + info.vertices = malloc(sizeof(GLdouble) * vertex_count * 3); + + /* Setup the tesselator */ + info.tobj = gluNewTess(); + gluTessCallback(info.tobj, GLU_TESS_BEGIN, (_GLUfuncptr) myBegin); + gluTessCallback(info.tobj, GLU_TESS_VERTEX, (_GLUfuncptr) myVertex); + gluTessCallback(info.tobj, GLU_TESS_COMBINE, (_GLUfuncptr) myCombine); + gluTessCallback(info.tobj, GLU_TESS_ERROR, (_GLUfuncptr) myError); + + /* Walk the polygon structure. Each iteration draws an island. For each island, all + * of the island's cutouts are drawn to the stencil buffer as a '1'. Then the island + * is drawn and areas where the stencil is set to a '1' are masked and not drawn. + */ + p_area = poly->Clipped; + do { + + /* Create a MASK (stencil). All following drawing will affect the mask only */ + drawgl_add_mask_create(); + + /* Find and draw the cutouts */ + pcb_r_search(p_area->contour_tree, clip_box, NULL, do_hole, &info, NULL); + drawgl_flush(); + + /* Use the mask while updating the colour buffer. All following drawing will update the + * colour buffer wherever the mask is not set + */ + drawgl_add_mask_use(); + + /* Draw the island to the colour buffer */ + tesselate_contour(info.tobj, p_area->contours, info.vertices, scale); + + /* destroy the current MASK */ + drawgl_add_mask_destroy(); + drawgl_flush(); + + p_area = p_area->f; + } while (fullpoly && (p_area != poly->Clipped)); + + gluDeleteTess(info.tobj); + myFreeCombined(); + free(info.vertices); +} + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.h =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.h (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/hidgl.h (revision 13657) @@ -0,0 +1,45 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2011 PCB 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. + * + */ + +#ifndef PCB_HID_COMMON_HIDGL_H +#define PCB_HID_COMMON_HIDGL_H + +#include "draw_gl.h" + +/*extern float global_depth;*/ +void hidgl_draw_local_grid(pcb_coord_t cx,pcb_coord_t cy,int radius); +void hidgl_draw_grid(pcb_box_t * drawn_area); +void hidgl_set_depth(float depth); +void hidgl_draw_line(int cap, pcb_coord_t width, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, double scale); +void hidgl_draw_arc(pcb_coord_t width, pcb_coord_t vx, pcb_coord_t vy, pcb_coord_t vrx, pcb_coord_t vry, pcb_angle_t start_angle, pcb_angle_t delta_angle, double scale); +void hidgl_draw_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +void hidgl_fill_circle(pcb_coord_t vx, pcb_coord_t vy, pcb_coord_t vr, double scale); +void hidgl_fill_polygon(int n_coords, pcb_coord_t * x, pcb_coord_t * y); +void hidgl_fill_polygon_offs(int n_coords, pcb_coord_t *x, pcb_coord_t *y, pcb_coord_t dx, pcb_coord_t dy); +void hidgl_fill_pcb_polygon(pcb_poly_t * poly, const pcb_box_t * clip_box, double scale); +void hidgl_fill_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2); +void hidgl_init(void); +void hidgl_set_drawing_mode(pcb_composite_op_t op, pcb_bool direct, const pcb_box_t * screen); + + +#endif /* PCB_HID_COMMON_HIDGL_H */ + Index: tags/1.2.7/src_plugins/hid_gtk2_gl/opengl.h.in =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/opengl.h.in (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/opengl.h.in (revision 13657) @@ -0,0 +1,54 @@ +print [@/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2011 PCB Contributers (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. + * + */ +#ifndef HID_GTK2_GL_OPENGL_H +#define HID_GTK2_GL_OPENGL_H +@] + +if ?/local/pcb/has_glu +then + +print [@ +/* The Linux OpenGL ABI 1.0 spec requires that we define + * GL_GLEXT_PROTOTYPES before including gl.h or glx.h for extensions + * in order to get prototypes: + * http://www.opengl.org/registry/ABI/ + */ +#define GL_GLEXT_PROTOTYPES 1 +#include <@libs/gui/gl/include_prefix@/gl.h> +#include <@libs/gui/gl/include_prefix@/glu.h> +@] + +else + +print [@ +/* if not calculating dependencies, including this header is an error when + opengl is not configured */ +#ifndef _PCB_DEP_ +# error opengl is not configured. +#endif +@] + +end + +print [@ +#endif /* ! defined HID_GTK2_GL_OPENGL_H */ +@] Index: tags/1.2.7/src_plugins/hid_gtk2_gl/pcb.rc =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/pcb.rc (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/pcb.rc (revision 13657) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.c (revision 13657) @@ -0,0 +1,111 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2011 PCB Contributers (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. + * + */ + +#include +#include + +#include "stencil_gl.h" + +static GLint stencil_bits = 0; +static int dirty_bits = 0; +static int assigned_bits = 0; + + +int stencilgl_bit_count() +{ + return stencil_bits; +} + +void stencilgl_clear_stencil_bits(int bits) +{ + glPushAttrib(GL_STENCIL_BUFFER_BIT); + glStencilMask(bits); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glPopAttrib(); + + dirty_bits = (dirty_bits & ~bits) | assigned_bits; +} + +void stencilgl_clear_unassigned_stencil() +{ + stencilgl_clear_stencil_bits(~assigned_bits); +} + +int stencilgl_allocate_clear_stencil_bit(void) +{ + int stencil_bitmask = (1 << stencil_bits) - 1; + int test; + int first_dirty = 0; + + if (assigned_bits == stencil_bitmask) { + printf("No more stencil bits available, total of %i already assigned\n", stencil_bits); + return 0; + } + + /* Look for a bitplane we don't have to clear */ + for (test = 1; test & stencil_bitmask; test <<= 1) { + if (!(test & dirty_bits)) { + assigned_bits |= test; + dirty_bits |= test; + return test; + } + else if (!first_dirty && !(test & assigned_bits)) { + first_dirty = test; + } + } + + /* Didn't find any non dirty planes. Clear those dirty ones which aren't in use */ + stencilgl_clear_unassigned_stencil(); + assigned_bits |= first_dirty; + dirty_bits = assigned_bits; + + return first_dirty; +} + +void stencilgl_return_stencil_bit(int bit) +{ + assigned_bits &= ~bit; +} + +void stencilgl_reset_stencil_usage() +{ + assigned_bits = 0; +} + +void +stencilgl_init() +{ + glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); + + if (stencil_bits == 0) { + printf("No stencil bits available.\n" "Cannot mask polygon holes or subcomposite layers\n"); + /* TODO: Flag this to the HID so it can revert to the dicer? */ + } + else if (stencil_bits == 1) { + printf("Only one stencil bitplane avilable\n" "Cannot use stencil buffer to sub-composite layers.\n"); + /* Do we need to disable that somewhere? */ + } + + stencilgl_reset_stencil_usage(); + stencilgl_clear_unassigned_stencil(); +} Index: tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.h =================================================================== --- tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.h (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk2_gl/stencil_gl.h (revision 13657) @@ -0,0 +1,68 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 2009-2017 PCB Contributers (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. + * + */ + +#ifndef STENCIL_GL_H +#define STENCIL_GL_H +/* +#include "config.h" +#include "conf_core.h" +#include +#include +#include +#include +#include +*/ + +#include "opengl.h" + +void stencilgl_init(); +int stencilgl_bit_count(); +void stencilgl_clear_stencil_bits(int bits); +void stencilgl_clear_unassigned_stencil(); +int stencilgl_allocate_clear_stencil_bit(); +void stencilgl_return_stencil_bit(int bit); +void stencilgl_reset_stencil_usage(); + +/* stencilgl_mode_write_set + * Setup the stencil buffer so that writes will set stencil bits + */ +static inline void +stencilgl_mode_write_set(int bits) +{ + glStencilOp(GL_KEEP,GL_KEEP,GL_REPLACE); + glStencilMask(bits); + glStencilFunc(GL_ALWAYS, bits, bits); +} + +/* stencilgl_mode_write_clear + * Setup the stencil buffer so that writes will clear stencil bits + */ +static inline void +stencilgl_mode_write_clear(int bits) +{ + glStencilOp(GL_KEEP,GL_KEEP,GL_ZERO); + glStencilMask(bits); + glStencilFunc(GL_ALWAYS, bits, bits); +} + +#endif /* !defined STENCIL_GL_H */ + Index: tags/1.2.7/src_plugins/hid_gtk3_cairo/Makefile =================================================================== --- tags/1.2.7/src_plugins/hid_gtk3_cairo/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk3_cairo/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk3_cairo + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/hid_gtk3_cairo/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/hid_gtk3_cairo/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk3_cairo/Plug.tmpasm (revision 13657) @@ -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/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (revision 13657) @@ -0,0 +1,1664 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * Copyright (C) 1994,1995,1996 Thomas Nau + * pcb-rnd Copyright (C) 2017 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 addresses for paper mail and Email: + * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany + * Thomas.Nau@rz.uni-ulm.de + * + */ + +#include "config.h" +#include "conf_core.h" + +#include + +#include "crosshair.h" +#include "clip.h" +#include "data.h" +#include "layer.h" +#include "hid_draw_helpers.h" +#include "hid_attrib.h" +#include "hid_helper.h" +#include "hid_color.h" + +#include "../src_plugins/lib_gtk_hid/gui.h" +#include "../src_plugins/lib_gtk_hid/coord_conv.h" + +#include "../src_plugins/lib_gtk_config/hid_gtk_conf.h" +#include "../src_plugins/lib_gtk_config/lib_gtk_config.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_hid_t *me_pointer; + + const char *colorname; /**< current color name for this GC. */ + 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 draw_lead_user(render_priv_t * priv_); + +/** Duplicates the source fields to destination. */ +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 \p color_string has been successfully parsed to \p 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); + if (fill) + /*FIXME: What means "fill a line" ? cairo_fill is not appropriate if path is only a line. */ + cairo_fill(cr); + else + cairo_stroke(cr); +} + +/** Destroys surface and context. */ +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; +} + +/** Called once per layer group. */ +static int ghid_cairo_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + 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 /*&& !pinout */ ); + } + + /* normal layers */ + if (idx >= 0 && idx < pcb_max_layer && ((flags & PCB_LYT_ANYTHING) != PCB_LYT_SILK)) + return /*pinout ? 1 : */ PCB->Data->Layer[idx].meta.real.vis; + + /* virtual layers */ + { + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return /* pinout ? 0 : */ PCB->InvisibleObjectsOn; + case PCB_LYT_SILK: + if (PCB_LAYERFLG_ON_VISIBLE_SIDE(flags) /*|| pinout */ ) + return pcb_silk_on(PCB); + return 0; + case PCB_LYT_ASSY: + return 0; + case PCB_LYT_PDRILL: + case PCB_LYT_UDRILL: + return 1; + case PCB_LYT_UI: + return 1; + case PCB_LYT_RAT: + return PCB->RatOn; + } + } + return 0; +} + +/** Called when all primitives of the current group have been created. */ +static void ghid_cairo_end_layer_group(void) +{ + end_subcomposite(); +} + +/** 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->colorname = conf_core.appearance.color.background; + return rv; +} + +/*TODO: 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); + /*FIXME: 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); + } +} + +void ghid_cairo_render_burst(pcb_burst_op_t op, const pcb_box_t *screen) +{ +} + +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; + } + + 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); + 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: + //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: + priv->cr = priv->cr_target; + //cairo_set_operator(priv->cr, CAIRO_OPERATOR_OVER); + //cairo_set_source_surface(priv->cr, priv->surf_layer, 0, 0); + 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], &priv->bg_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/background"), -1); + //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], &priv->offlimits_color)) { + config_color_button_update(&ghidgui->common, conf_get_field("appearance/color/off_limit"), -1); + //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], &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 char *name) +{ + static void *cache = 0; + pcb_hidval_t cval; + render_priv_t *priv = gport->render_priv; + + if (name == NULL) { + fprintf(stderr, "ghid_cairo_set_color(): name = NULL, setting to magenta\n"); + name = "magenta"; + } + + //if (name != gc->colorname) { + // if (gc->colorname != NULL) + // g_free(gc->colorname); + // gc->colorname = g_strdup(name); + //} + gc->colorname = name; + + //if (!gc->gc) + // return; + //if (gport->colormap == 0) + // gport->colormap = gtk_widget_get_colormap(gport->top_window); + + if (strcmp(name, "erase") == 0) { + copy_color(&gc->color, &priv->bg_color); + //gdk_cairo_set_source_rgba(cr, &priv->bg_color); + //gdk_gc_set_foreground(gc->gc, &gport->bg_color); + } + else if (strcmp(name, "drill") == 0) { + 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 Trace_Cap: + case Round_Cap: + cap = CAIRO_LINE_CAP_ROUND; + join = CAIRO_LINE_JOIN_ROUND; + break; + case Square_Cap: + case Beveled_Cap: + cap = CAIRO_LINE_CAP_SQUARE; + join = CAIRO_LINE_JOIN_MITER; + break; + } + 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->colorname); +} + +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->colorname); + gdk_cairo_set_source_rgba(cr, &gc->color); + //ghid_cairo_set_line_width(gc, gc->width); + 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); +} + +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) +{ + gint vrx2, vry2; + double w, h, radius; + 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); + 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; + + cairo_save(priv->cr); + /*FIXME: 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), + (start_angle) * (M_PI / 180.0), delta_angle * (M_PI / 180.0)); + 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); +} + +/** Draws a rectangle */ +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); +} + +/** Paints the \p surface onto the \p cr cairo context */ +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); +} + +/* Intentaional code duplication 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); +} + +/* Intentaional code duplication for performance */ +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 + dx, _y + dy); + else + cairo_line_to(cr, _x + dx, _y + dy); + } + cairo_fill(cr); +} + +/** Fills the drawing with only \p 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)); + + ctx.force = 0; + ctx.content.obj = NULL; + + 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); + ghid_cairo_draw_grid(); + + /* Draws "GUI" information on top of design */ + priv->cr = priv->cr_drawing_area; + pcb_draw_attached(); + pcb_draw_mark(); + + draw_lead_user(priv); + + 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(); + + 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; + + 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) + return; + + /* FIXME: when CrossColor changed from config */ + map_color_string(conf_core.appearance.color.cross, &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); + // /* FIXME: when CrossColor changed from config */ + // map_color_string(conf_core.appearance.color.cross, &cross_color); + //} + x = DRAW_X(&gport->view, gport->view.crosshair_x); + y = DRAW_Y(&gport->view, 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) +{ +} + +/** Call-back 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, &priv->bg_color)) + map_color_string("white", &priv->bg_color); + + if (!map_color_string(conf_core.appearance.color.off_limit, &priv->offlimits_color)) + map_color_string("white", &priv->offlimits_color); + + if (!map_color_string(conf_core.appearance.color.grid, &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, const 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; + + 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; + + /* 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); + /* calls the off-line drawing routine */ + expcall(>k3_cairo_hid, ctx); + cairo_restore(p); + priv->cr = priv->cr_drawing_area; + //gport->drawable = save_drawable; + + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static pcb_hid_t *ghid_cairo_request_debug_draw(void) +{ + /* No special setup requirements, drawing goes into + * the backing pixmap in GTK2. */ + return >k3_cairo_hid; +} + +static void ghid_cairo_flush_debug_draw(void) +{ + ghid_cairo_screen_update(); + gdk_flush(); +} + +static void ghid_cairo_finish_debug_draw(void) +{ + ghid_cairo_flush_debug_draw(); + /* No special tear down requirements + */ +} + +static void draw_lead_user(render_priv_t * priv) +{ + //GdkWindow *window = gtk_widget_get_window(gport->drawing_area); + //GtkStyle *style = gtk_widget_get_style(gport->drawing_area); + int i; + pcb_lead_user_t *lead_user = &gport->lead_user; + pcb_coord_t radius = lead_user->radius; + pcb_coord_t width = PCB_MM_TO_COORD(LEAD_USER_WIDTH); + pcb_coord_t separation = PCB_MM_TO_COORD(LEAD_USER_ARC_SEPARATION); + //static GdkGC *lead_gc = NULL; + //GdkColor lead_color; + + if (!lead_user->lead_user) + return; + + //if (lead_gc == NULL) { + // lead_gc = gdk_gc_new(window); + // gdk_gc_copy(lead_gc, style->white_gc); + // gdk_gc_set_function(lead_gc, GDK_XOR); + // gdk_gc_set_clip_origin(lead_gc, 0, 0); + // lead_color.pixel = 0; + // lead_color.red = (int) (65535. * LEAD_USER_COLOR_R); + // lead_color.green = (int) (65535. * LEAD_USER_COLOR_G); + // lead_color.blue = (int) (65535. * LEAD_USER_COLOR_B); + // gdk_color_alloc(gport->colormap, &lead_color); + // gdk_gc_set_foreground(lead_gc, &lead_color); + //} + + //set_clip(priv, lead_gc); + //gdk_gc_set_line_attributes(lead_gc, Vz(width), GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); + + /* arcs at the appropriate radii */ + + for (i = 0; i < LEAD_USER_ARC_COUNT; i++, radius -= separation) { + if (radius < width) + radius += PCB_MM_TO_COORD(LEAD_USER_INITIAL_RADIUS); + + /* Draw an arc at radius */ + //gdk_draw_arc(gport->drawable, lead_gc, FALSE, + // Vx(lead_user->x - radius), Vy(lead_user->y - radius), Vz(2. * radius), Vz(2. * radius), 0, 360 * 64); + } +} + +void ghid_cairo_install(pcb_gtk_common_t * common, pcb_hid_t * hid) +{ + if (common != NULL) { + 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; + + hid->request_debug_draw = ghid_cairo_request_debug_draw; + hid->flush_debug_draw = ghid_cairo_flush_debug_draw; + hid->finish_debug_draw = ghid_cairo_finish_debug_draw; + + } +} Index: tags/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-main.c =================================================================== --- tags/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-main.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk3_cairo/gtkhid-main.c (revision 13657) @@ -0,0 +1,69 @@ +#include "config.h" + +#include + +#include "action_helper.h" +#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_config/lib_gtk_config.h" +#include "../src_plugins/lib_gtk_config/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); + +void gtk3_cairo_parse_arguments(int *argc, char ***argv) +{ + ghid_cairo_install(&ghidgui->common, NULL); + 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) +{ + 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/1.2.7/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup =================================================================== --- tags/1.2.7/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (nonexistent) +++ tags/1.2.7/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (revision 13657) @@ -0,0 +1,11 @@ +$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_config +dep lib_gtk_hid +dep draw_csect +dep draw_fontsel +autoload 1 Index: tags/1.2.7/src_plugins/hid_lesstif/Makefile =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/Makefile (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/Makefile (revision 13657) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_lesstif + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.7/src_plugins/hid_lesstif/Plug.tmpasm =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/Plug.tmpasm (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/Plug.tmpasm (revision 13657) @@ -0,0 +1,44 @@ +put /local/pcb/mod {hid_lesstif} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/hid_lesstif/dialogs.o + $(PLUGDIR)/hid_lesstif/library.o + $(PLUGDIR)/hid_lesstif/main.o + $(PLUGDIR)/hid_lesstif/menu.o + $(PLUGDIR)/hid_lesstif/menu_lht.o + $(PLUGDIR)/hid_lesstif/netlist.o + $(PLUGDIR)/hid_lesstif/styles.o + $(PLUGDIR)/hid_lesstif/stdarg.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 + +# always generate the menu lht rule so make dep can be run +append /local/pcb/CLEANFILES { $(PLUGDIR)/hid_lesstif/menu_lht.c } +append /local/pcb/DEPDEPS { $(PLUGDIR)/hid_lesstif/menu_lht.c } +append /local/pcb/RULES [@ +### lesstif menu embed +$(PLUGDIR)/hid_lesstif/menu_lht.c: pcb-menu-lesstif.lht $(CQUOTE) + $(CQUOTE) -n lesstif_menu_default $(PLUGDIR)/hid_lesstif/menu_lht.c +@] + + +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/1.2.7/src_plugins/hid_lesstif/dialogs.c =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/dialogs.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/dialogs.c (revision 13657) @@ -0,0 +1,2017 @@ +#include "xincludes.h" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include + + +#include "compat_misc.h" +#include "data.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 "hid_actions.h" +#include "hid_init.h" +#include "stdarg.h" +#include "misc_util.h" +#include "compat_nls.h" +#include "compat_misc.h" +#include "search.h" +#include "action_helper.h" +#include "change.h" + +static int ok; + +#define COMPONENT_SIDE_NAME "(top)" +#define SOLDER_SIDE_NAME "(bottom)" + +/* ------------------------------------------------------------ */ + +static void dialog_callback_ok_value(Widget w, void *v, void *cbs) +{ + ok = (int) (size_t) v; +} + +typedef struct { + void (*cb)(void *ctx, pcb_hid_attr_ev_t ev); + void *ctx; +} dialog_cb_ctx_t; + +static void dialog_callback_cancel(Widget w, void *v, void *cbs) +{ + dialog_cb_ctx_t *ctx = (dialog_cb_ctx_t *)v; + if (ctx != NULL) { + ctx->cb(ctx->ctx, PCB_HID_ATTR_EV_CANCEL); + free(ctx); + } + ok = 0; +} + +static void dialog_callback_ok(Widget w, void *v, void *cbs) +{ + dialog_cb_ctx_t *ctx = (dialog_cb_ctx_t *)v; + if (ctx != NULL) { + ctx->cb(ctx->ctx, PCB_HID_ATTR_EV_OK); + free(ctx); + } + ok = 1; +} + +static int wait_for_dialog(Widget w) +{ + ok = -1; + XtManageChild(w); + while (ok == -1 && XtIsManaged(w)) { + XEvent e; + XtAppNextEvent(app_context, &e); + XtDispatchEvent(&e); + } + XtUnmanageChild(w); + return ok; +} + +/* ------------------------------------------------------------ */ + +static Widget fsb = 0; +static XmString xms_pcb, xms_net, xms_vend, xms_all, xms_load, xms_loadv, xms_save, xms_fp; + +static void setup_fsb_dialog() +{ + if (fsb) + return; + + xms_pcb = XmStringCreatePCB("*.pcb"); + xms_fp = XmStringCreatePCB("*.fp"); + xms_net = XmStringCreatePCB("*.net"); + xms_vend = XmStringCreatePCB("*.vend"); + xms_all = XmStringCreatePCB("*"); + xms_load = XmStringCreatePCB("Load From"); + xms_loadv = XmStringCreatePCB("Load Vendor"); + xms_save = XmStringCreatePCB("Save As"); + + stdarg_n = 0; + fsb = XmCreateFileSelectionDialog(mainwind, XmStrCast("file"), stdarg_args, stdarg_n); + + XtAddCallback(fsb, XmNokCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 1); + XtAddCallback(fsb, XmNcancelCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 0); +} + +static const char load_syntax[] = "Load()\n" "Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert)"; + +static const char load_help[] = "Load layout data from a user-selected file."; + +/* %start-doc actions Load + +This action is a GUI front-end to the core's @code{LoadFrom} action +(@pxref{LoadFrom Action}). If you happen to pass a filename, like +@code{LoadFrom}, then @code{LoadFrom} is called directly. Else, the +user is prompted for a filename to load, and then @code{LoadFrom} is +called with that filename. + +%end-doc */ + +static int Load(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function; + char *name; + XmString xmname, pattern; + + if (argc > 1) + return pcb_hid_actionv("LoadFrom", argc, argv); + + function = argc ? argv[0] : "Layout"; + + setup_fsb_dialog(); + + if (pcb_strcasecmp(function, "Netlist") == 0) + pattern = xms_net; + else if (pcb_strcasecmp(function, "ElementToBuffer") == 0) + pattern = xms_fp; + else + pattern = xms_pcb; + + stdarg_n = 0; + stdarg(XmNtitle, "Load From"); + XtSetValues(XtParent(fsb), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNpattern, pattern); + stdarg(XmNmustMatch, True); + stdarg(XmNselectionLabelString, xms_load); + XtSetValues(fsb, stdarg_args, stdarg_n); + + if (!wait_for_dialog(fsb)) + return 1; + + stdarg_n = 0; + stdarg(XmNdirSpec, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &name); + + pcb_hid_actionl("LoadFrom", function, name, NULL); + + XtFree(name); + + return 0; +} + +static const char loadvendor_syntax[] = "LoadVendor()"; + +static const char loadvendor_help[] = "Loads a user-selected vendor resource file."; + +/* %start-doc actions LoadVendor + +The user is prompted for a file to load, and then +@code{LoadVendorFrom} is called (@pxref{LoadVendorFrom Action}) to +load that vendor file. + +%end-doc */ + +static int LoadVendor(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + char *name; + XmString xmname, pattern; + + if (argc > 0) + return pcb_hid_actionv("LoadVendorFrom", argc, argv); + + setup_fsb_dialog(); + + pattern = xms_vend; + + stdarg_n = 0; + stdarg(XmNtitle, "Load Vendor"); + XtSetValues(XtParent(fsb), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNpattern, pattern); + stdarg(XmNmustMatch, True); + stdarg(XmNselectionLabelString, xms_loadv); + XtSetValues(fsb, stdarg_args, stdarg_n); + + if (!wait_for_dialog(fsb)) + return 1; + + stdarg_n = 0; + stdarg(XmNdirSpec, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &name); + + pcb_hid_actionl("LoadVendorFrom", name, NULL); + + XtFree(name); + + return 0; +} + +static const char save_syntax[] = + "Save()\n" "Save(Layout|LayoutAs)\n" "Save(AllConnections|AllUnusedPins|ElementConnections)\n" "Save(PasteBuffer)"; + +static const char save_help[] = "Save layout data to a user-selected file."; + +/* %start-doc actions Save + +This action is a GUI front-end to the core's @code{SaveTo} action +(@pxref{SaveTo Action}). If you happen to pass a filename, like +@code{SaveTo}, then @code{SaveTo} is called directly. Else, the +user is prompted for a filename to save, and then @code{SaveTo} is +called with that filename. + +%end-doc */ + +static int Save(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *function; + char *name; + XmString xmname, pattern; + + if (argc > 1) + pcb_hid_actionv("SaveTo", argc, argv); + + function = argc ? argv[0] : "Layout"; + + if (pcb_strcasecmp(function, "Layout") == 0) + if (PCB->Filename) + return pcb_hid_actionl("SaveTo", "Layout", PCB->Filename, NULL); + + setup_fsb_dialog(); + + pattern = xms_pcb; + + XtManageChild(fsb); + + stdarg_n = 0; + stdarg(XmNtitle, "Save As"); + XtSetValues(XtParent(fsb), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNpattern, pattern); + stdarg(XmNmustMatch, False); + stdarg(XmNselectionLabelString, xms_save); + XtSetValues(fsb, stdarg_args, stdarg_n); + + if (!wait_for_dialog(fsb)) + return 1; + + stdarg_n = 0; + stdarg(XmNdirSpec, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &name); + + if (pcb_strcasecmp(function, "PasteBuffer") == 0) + pcb_hid_actionl("PasteBuffer", "Save", name, NULL); + else { + /* + * 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 (pcb_strcasecmp(function, "Layout") == 0) + pcb_hid_actionl("SaveTo", "LayoutAs", name, NULL); + else + pcb_hid_actionl("SaveTo", function, name, NULL); + } + XtFree(name); + + return 0; +} + +/* ------------------------------------------------------------ */ + +static Widget log_form, log_text; +static int log_size = 0; +static int pending_newline = 0; + +static void log_clear(Widget w, void *up, void *cbp) +{ + XmTextSetString(log_text, XmStrCast("")); + log_size = 0; + pending_newline = 0; +} + +static void log_dismiss(Widget w, void *up, void *cbp) +{ + XtUnmanageChild(log_form); +} + +void lesstif_logv(enum pcb_message_level level, const char *fmt, va_list ap) +{ + char *buf, *scan; + if (!mainwind) { + vprintf(fmt, ap); + return; + } + if (!log_form) { + Widget clear_button, dismiss_button; + + stdarg_n = 0; + stdarg(XmNautoUnmanage, False); + stdarg(XmNwidth, 600); + stdarg(XmNheight, 200); + stdarg(XmNtitle, "pcb-rnd Log"); + log_form = XmCreateFormDialog(mainwind, XmStrCast("log"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + clear_button = XmCreatePushButton(log_form, XmStrCast("clear"), stdarg_args, stdarg_n); + XtManageChild(clear_button); + XtAddCallback(clear_button, XmNactivateCallback, (XtCallbackProc) log_clear, 0); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_WIDGET); + stdarg(XmNrightWidget, clear_button); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + dismiss_button = XmCreatePushButton(log_form, XmStrCast("dismiss"), stdarg_args, stdarg_n); + XtManageChild(dismiss_button); + XtAddCallback(dismiss_button, XmNactivateCallback, (XtCallbackProc) log_dismiss, 0); + + stdarg_n = 0; + stdarg(XmNeditable, False); + stdarg(XmNeditMode, XmMULTI_LINE_EDIT); + stdarg(XmNcursorPositionVisible, True); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, clear_button); + log_text = XmCreateScrolledText(log_form, XmStrCast("text"), stdarg_args, stdarg_n); + XtManageChild(log_text); + + XtManageChild(log_form); + } + if (pending_newline) { + XmTextInsert(log_text, log_size++, XmStrCast("\n")); + pending_newline = 0; + } + buf = pcb_strdup_vprintf(fmt, ap); + scan = &buf[strlen(buf) - 1]; + while (scan >= buf && *scan == '\n') { + pending_newline++; + *scan-- = 0; + } + switch(level) { + case PCB_MSG_ERROR: XmTextInsert(log_text, log_size, "Err: "); break; + case PCB_MSG_WARNING: XmTextInsert(log_text, log_size, "Wrn: "); break; + case PCB_MSG_INFO: XmTextInsert(log_text, log_size, "Inf: "); break; + case PCB_MSG_DEBUG: XmTextInsert(log_text, log_size, "Dbg: "); break; + } + log_size += 5; + XmTextInsert(log_text, log_size, buf); + log_size += strlen(buf); + + scan = strrchr(buf, '\n'); + if (scan) + scan++; + else + scan = buf; + XmTextSetCursorPosition(log_text, log_size - strlen(scan)); + free(buf); +} + +void lesstif_log(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + lesstif_logv(PCB_MSG_INFO, fmt, ap); + va_end(ap); +} + +/* ------------------------------------------------------------ */ + +static Widget confirm_dialog = 0; +static Widget confirm_cancel, confirm_ok, confirm_label; + +int lesstif_confirm_dialog(const char *msg, ...) +{ + const char *cancelmsg, *okmsg; + va_list ap; + XmString xs; + + if (mainwind == 0) + return 1; + + if (confirm_dialog == 0) { + stdarg_n = 0; + stdarg(XmNdefaultButtonType, XmDIALOG_OK_BUTTON); + stdarg(XmNtitle, "Confirm"); + confirm_dialog = XmCreateQuestionDialog(mainwind, XmStrCast("confirm"), stdarg_args, stdarg_n); + XtAddCallback(confirm_dialog, XmNcancelCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 0); + XtAddCallback(confirm_dialog, XmNokCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 1); + + confirm_cancel = XmMessageBoxGetChild(confirm_dialog, XmDIALOG_CANCEL_BUTTON); + confirm_ok = XmMessageBoxGetChild(confirm_dialog, XmDIALOG_OK_BUTTON); + confirm_label = XmMessageBoxGetChild(confirm_dialog, XmDIALOG_MESSAGE_LABEL); + XtUnmanageChild(XmMessageBoxGetChild(confirm_dialog, XmDIALOG_HELP_BUTTON)); + } + + va_start(ap, msg); + cancelmsg = va_arg(ap, const char *); + okmsg = va_arg(ap, const char *); + va_end(ap); + + if (!cancelmsg) { + cancelmsg = "Cancel"; + okmsg = "Ok"; + } + + stdarg_n = 0; + xs = XmStringCreatePCB(cancelmsg); + + if (okmsg) { + stdarg(XmNcancelLabelString, xs); + xs = XmStringCreatePCB(okmsg); + XtManageChild(confirm_cancel); + } + else + XtUnmanageChild(confirm_cancel); + + stdarg(XmNokLabelString, xs); + + xs = XmStringCreatePCB(msg); + stdarg(XmNmessageString, xs); + XtSetValues(confirm_dialog, stdarg_args, stdarg_n); + + wait_for_dialog(confirm_dialog); + + stdarg_n = 0; + stdarg(XmNdefaultPosition, False); + XtSetValues(confirm_dialog, stdarg_args, stdarg_n); + + return ok; +} + +static int ConfirmAction(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int rv = lesstif_confirm_dialog(argc > 0 ? argv[0] : 0, + argc > 1 ? argv[1] : 0, + argc > 2 ? argv[2] : 0, + 0); + return rv; +} + +/* ------------------------------------------------------------ */ + +int lesstif_close_confirm_dialog() +{ + return lesstif_confirm_dialog("OK to lose data ?", NULL); +} + +/* ------------------------------------------------------------ */ + +static Widget report = 0, report_form; + +void lesstif_report_dialog(const char *title, const char *msg) +{ + if (!report) { + if (mainwind == 0) + return; + + stdarg_n = 0; + stdarg(XmNautoUnmanage, False); + stdarg(XmNwidth, 600); + stdarg(XmNheight, 200); + stdarg(XmNtitle, title); + report_form = XmCreateFormDialog(mainwind, XmStrCast("report"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNeditable, False); + stdarg(XmNeditMode, XmMULTI_LINE_EDIT); + stdarg(XmNcursorPositionVisible, False); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + report = XmCreateScrolledText(report_form, XmStrCast("text"), stdarg_args, stdarg_n); + XtManageChild(report); + } + stdarg_n = 0; + stdarg(XmNtitle, title); + XtSetValues(report_form, stdarg_args, stdarg_n); + XmTextSetString(report, (char *) msg); + + XtManageChild(report_form); +} + +/* ------------------------------------------------------------ */ +/* FIXME -- make this a proper file select dialog box */ +char *lesstif_fileselect(const char *title, const char *descr, + const char *default_file, const char *default_ext, const char *history_tag, int flags) +{ + + return lesstif_prompt_for(title, default_file); +} + +/* ------------------------------------------------------------ */ + +static Widget prompt_dialog = 0; +static Widget prompt_label, prompt_text; + +char *lesstif_prompt_for(const char *msg, const char *default_string) +{ + char *rv; + XmString xs; + if (prompt_dialog == 0) { + stdarg_n = 0; + stdarg(XmNautoUnmanage, False); + stdarg(XmNtitle, "pcb-rnd Prompt"); + prompt_dialog = XmCreateFormDialog(mainwind, XmStrCast("prompt"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNalignment, XmALIGNMENT_BEGINNING); + prompt_label = XmCreateLabel(prompt_dialog, XmStrCast("label"), stdarg_args, stdarg_n); + XtManageChild(prompt_label); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_WIDGET); + stdarg(XmNtopWidget, prompt_label); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNeditable, True); + prompt_text = XmCreateText(prompt_dialog, XmStrCast("text"), stdarg_args, stdarg_n); + XtManageChild(prompt_text); + XtAddCallback(prompt_text, XmNactivateCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) 1); + } + if (!default_string) + default_string = ""; + if (!msg) + msg = "Enter text:"; + stdarg_n = 0; + xs = XmStringCreatePCB(msg); + stdarg(XmNlabelString, xs); + XtSetValues(prompt_label, stdarg_args, stdarg_n); + XmTextSetString(prompt_text, (char *) default_string); + XmTextSetCursorPosition(prompt_text, strlen(default_string)); + wait_for_dialog(prompt_dialog); + rv = XmTextGetString(prompt_text); + return rv; +} + +static const char promptfor_syntax[] = "PromptFor([message[,default]])"; + +static const char promptfor_help[] = "Prompt for a response."; + +/* %start-doc actions PromptFor + +This is mostly for testing the lesstif HID interface. The parameters +are passed to the @code{prompt_for()} HID function, causing the user +to be prompted for a response. The respose is simply printed to the +user's stdout. + +%end-doc */ + +static int PromptFor(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + char *rv = lesstif_prompt_for(argc > 0 ? argv[0] : 0, + argc > 1 ? argv[1] : 0); + printf("rv = `%s'\n", rv); + return 0; +} + +/* ------------------------------------------------------------ */ + +static Widget create_form_ok_dialog(const char *name, int ok, void (*button_cb)(void *ctx, pcb_hid_attr_ev_t ev), void *ctx) +{ + Widget dialog, topform; + dialog_cb_ctx_t *cb_ctx = NULL; + + stdarg_n = 0; + dialog = XmCreateQuestionDialog(mainwind, XmStrCast(name), stdarg_args, stdarg_n); + + if (button_cb != NULL) { + cb_ctx = malloc(sizeof(dialog_cb_ctx_t)); + cb_ctx->cb = button_cb; + cb_ctx->ctx = ctx; + } + + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_SYMBOL_LABEL)); + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_MESSAGE_LABEL)); + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); + XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc) dialog_callback_cancel, cb_ctx); + if (ok) + XtAddCallback(dialog, XmNokCallback, (XtCallbackProc) dialog_callback_ok, cb_ctx); + else + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON)); + + stdarg_n = 0; + topform = XmCreateForm(dialog, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(topform); + return topform; +} + +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); + 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(XmNorientation, XmHORIZONTAL); + stdarg(XmNpacking, XmPACK_TIGHT); + break; + case 'v': /* "vbox" */ + stdarg(XmNorientation, XmVERTICAL); + stdarg(XmNpacking, XmPACK_COLUMN); + break; + case 't': /* "table" */ + stdarg(XmNorientation, XmHORIZONTAL); + stdarg(XmNpacking, XmPACK_COLUMN); + stdarg(XmNnumColumns, num_table_rows); + stdarg(XmNisAligned, True); + stdarg(XmNentryAlignment, XmALIGNMENT_END); + break; + default: + abort(); + } + cnt = XmCreateRowColumn(parent, name, stdarg_args, stdarg_n); + return cnt; +} + +typedef struct { + pcb_hid_attribute_t *attrs; + int n_attrs, actual_nattrs; + Widget *wl; + 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]; + unsigned inhibit_valchg: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 = ctx->results[widx].int_value = XmToggleButtonGetState(ctx->wl[widx]); + break; + case PCB_HATT_STRING: + ctx->results[widx].str_value = pcb_strdup(XmTextGetString(ctx->wl[widx])); + break; + case PCB_HATT_INTEGER: + cp = XmTextGetString(ctx->wl[widx]); + sscanf(cp, "%d", &ctx->results[widx].int_value); + break; + case PCB_HATT_COORD: + cp = XmTextGetString(ctx->wl[widx]); + ctx->results[widx].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->results[widx].int_value = uptr - ctx->attrs[widx].enumerations; + } + break; + default: + break; + } + ctx->attrs[widx].default_val = ctx->results[widx]; +} + +static void valchg(Widget w, XtPointer dlg_widget_, XtPointer call_data) +{ + lesstif_attr_dlg_t *ctx; + Widget dlg_widget = (Widget)dlg_widget_; /* ctx->wl[i] */ + int widx; + + if (dlg_widget == NULL) + return; + + XtVaGetValues(dlg_widget, XmNuserData, &ctx, NULL); + + if (ctx == NULL) + return; + + if (ctx->inhibit_valchg) + return; + + for(widx = 0; widx < ctx->n_attrs; widx++) + if (ctx->wl[widx] == dlg_widget) + break; + + if (widx >= ctx->n_attrs) + return; + + ctx->attrs[widx].changed = 1; + + if ((ctx->attrs[widx].change_cb == NULL) && (ctx->property[PCB_HATP_GLOBAL_CALLBACK].func == NULL)) + return; + + attribute_dialog_readres(ctx, widx); + 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]); +} + +/* 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 add_labels) +{ + 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 label */ + if ((add_labels) && (ctx->attrs[i].type != PCB_HATT_LABEL)) { + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_END); + w = XmCreateLabel(parent, XmStrCast(ctx->attrs[i].name), stdarg_args, stdarg_n); + XtManageChild(w); + } + + /* Add content */ + stdarg_n = 0; + stdarg(XmNalignment, XmALIGNMENT_END); + 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, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_LABEL)); + 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, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_LABEL)); + break; + + case PCB_HATT_BEGIN_TABLE: + /* create content table */ + numcol = ctx->attrs[i].pcb_hatt_table_cols; + len = pcb_hid_atrdlg_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, (ctx->attrs[i].pcb_hatt_flags & PCB_HATF_LABEL)); + 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_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]); + 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_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]); + } + 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; + + 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_END: + goto err; + 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); + 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_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:; + ctx->attrs[idx].default_val = *val; + ctx->inhibit_valchg = save; + return 0; + + err:; + ctx->inhibit_valchg = save; + return -1; +} + +void *lesstif_attr_dlg_new(pcb_hid_attribute_t *attrs, int n_attrs, pcb_hid_attr_val_t *results, const char *title, const char *descr, void *caller_data, pcb_bool modal, void (*button_cb)(void *caller_data, pcb_hid_attr_ev_t ev)) +{ + 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; + + 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->btn = (Widget **) calloc(n_attrs, sizeof(Widget *)); + + topform = create_form_ok_dialog(title, 1, button_cb, caller_data); + ctx->dialog = XtParent(topform); + + 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_atrdlg_num_children(ctx->attrs, 0, ctx->n_attrs), 0, 0); + XtManageChild(main_tbl); + attribute_dialog_add(ctx, main_tbl, 0, 1); + } + else + attribute_dialog_add(ctx, topform, 0, (ctx->attrs[0].pcb_hatt_flags & PCB_HATF_LABEL)); + + if (!modal) + XtManageChild(ctx->dialog); + + return ctx; +} + +int lesstif_attr_dlg_run(void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + return wait_for_dialog(ctx->dialog); +} + +void lesstif_attr_dlg_free(void *hid_ctx) +{ + lesstif_attr_dlg_t *ctx = hid_ctx; + int i; + + for (i = 0; i < ctx->n_attrs; i++) { + attribute_dialog_readres(ctx, i); + free(ctx->btn[i]); + } + + free(ctx->wl); + XtDestroyWidget(ctx->dialog); + 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_attribute_dialog(pcb_hid_attribute_t * attrs, int n_attrs, pcb_hid_attr_val_t * results, const char *title, const char *descr, void *caller_data) +{ + int rv; + void *hid_ctx; + + hid_ctx = lesstif_attr_dlg_new(attrs, n_attrs, results, title, descr, caller_data, pcb_true, NULL); + rv = lesstif_attr_dlg_run(hid_ctx); + lesstif_attr_dlg_free(hid_ctx); + + return rv ? 0 : 1; +} + +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; + + 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 (hide) + XtUnmanageChild(ctx->wl[idx]); + else + XtManageChild(ctx->wl[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 dowindows_syntax[] = "DoWindows(1|2|3|4)\n" "DoWindows(Layout|Library|Log|Netlist)"; + +static const char dowindows_help[] = "Open various GUI windows."; + +/* %start-doc actions DoWindows + +@table @code + +@item 1 +@itemx Layout +Open the layout window. Since the layout window is always shown +anyway, this has no effect. + +@item 2 +@itemx Library +Open the library window. + +@item 3 +@itemx Log +Open the log window. + +@item 4 +@itemx Netlist +Open the netlist window. + +@end table + +%end-doc */ + +static int DoWindows(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *a = argc == 1 ? argv[0] : ""; + 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) { + if (log_form == 0) + lesstif_log(""); + XtManageChild(log_form); + } + else if (strcmp(a, "4") == 0 || pcb_strcasecmp(a, "Netlist") == 0) { + lesstif_show_netlist(); + } + else { + lesstif_log("Usage: DoWindows(1|2|3|4|Layout|Library|Log|Netlist)"); + return 1; + } + return 0; +} + +/* ------------------------------------------------------------ */ +static const char about_syntax[] = "About()"; + +static const char about_help[] = "Tell the user about this version of PCB."; + +/* %start-doc actions About + +This just pops up a dialog telling the user which version of +@code{pcb} they're running. + +%end-doc */ + + +static int About(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + static Widget about = 0; + if (!about) { + XmString xs; + stdarg_n = 0; + xs = XmStringCreatePCB(pcb_get_infostr()); + stdarg(XmNmessageString, xs); + stdarg(XmNtitle, "About pcb-rnd"); + about = XmCreateInformationDialog(mainwind, XmStrCast("about"), stdarg_args, stdarg_n); + XtUnmanageChild(XmMessageBoxGetChild(about, XmDIALOG_CANCEL_BUTTON)); + XtUnmanageChild(XmMessageBoxGetChild(about, XmDIALOG_HELP_BUTTON)); + } + wait_for_dialog(about); + return 0; +} + +/* ------------------------------------------------------------ */ + +static const char print_syntax[] = "Print()"; + +static const char print_help[] = "Print the layout."; + +/* %start-doc actions Print + +This will find the default printing HID, prompt the user for its +options, and print the layout. + +%end-doc */ + +static int Print(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_hid_attribute_t *opts; + pcb_hid_t *printer; + pcb_hid_attr_val_t *vals; + int n; + + printer = pcb_hid_find_printer(); + if (!printer) { + lesstif_confirm_dialog("No printer?", "Oh well", 0); + return 1; + } + opts = printer->get_export_options(&n); + vals = (pcb_hid_attr_val_t *) calloc(n, sizeof(pcb_hid_attr_val_t)); + if (lesstif_attribute_dialog(opts, n, vals, "Print", "", NULL)) { + free(vals); + return 1; + } + printer->do_export(vals); + free(vals); + return 0; +} + +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]; + +static const char printcalibrate_syntax[] = "PrintCalibrate()"; + +static const char printcalibrate_help[] = "Calibrate the printer."; + +/* %start-doc actions PrintCalibrate + +This will print a calibration page, which you would measure and type +the measurements in, so that future printouts will be more precise. + +%end-doc */ + +static int PrintCalibrate(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_hid_t *printer = pcb_hid_find_printer(); + printer->calibrate(0.0, 0.0); + if (pcb_gui->attribute_dialog(printer_calibrate_attrs, 3, + printer_calibrate_values, + "Printer Calibration Values", "Enter calibration values for your printer", NULL)) + return 1; + printer->calibrate(printer_calibrate_values[1].real_value, printer_calibrate_values[2].real_value); + return 0; +} + +static const char exportgui_syntax[] = "ExportGUI()"; + +static const char exportgui_help[] = "Export the layout. Export is configured using dialog a box."; + +/* %start-doc actions Export + +Prompts the user for an exporter to use. Then, prompts the user for +that exporter's options, and exports the layout. + +%end-doc */ + +static int ExportGUI(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + static Widget selector = 0; + pcb_hid_attribute_t *opts; + pcb_hid_t *printer, **hids; + pcb_hid_attr_val_t *vals; + int n, i, count; + Widget prev = 0; + Widget w; + + hids = pcb_hid_enumerate(); + + if (!selector) { + stdarg_n = 0; + stdarg(XmNtitle, "Export HIDs"); + selector = create_form_ok_dialog("export", 0, NULL, NULL); + count = 0; + for (i = 0; hids[i]; i++) { + if (hids[i]->exporter) { + stdarg_n = 0; + if (prev) { + stdarg(XmNtopAttachment, XmATTACH_WIDGET); + stdarg(XmNtopWidget, prev); + } + else { + stdarg(XmNtopAttachment, XmATTACH_FORM); + } + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + w = XmCreatePushButton(selector, (char *) hids[i]->name, stdarg_args, stdarg_n); + XtManageChild(w); + XtAddCallback(w, XmNactivateCallback, (XtCallbackProc) dialog_callback_ok_value, (XtPointer) ((size_t) i + 1)); + prev = w; + count++; + } + } + if (count == 0) { + Widget label; + stdarg_n = 0; + stdarg(XmNlabelString, XmStringCreatePCB("No exporter found. Check your plugins!")); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + label = XmCreateLabel(selector, XmStrCast("label"), stdarg_args, stdarg_n); + XtManageChild(label); + } + selector = XtParent(selector); + } + + + i = wait_for_dialog(selector); + + if (i <= 0) + return 1; + printer = hids[i - 1]; + + pcb_exporter = printer; + + opts = printer->get_export_options(&n); + vals = (pcb_hid_attr_val_t *) calloc(n, sizeof(pcb_hid_attr_val_t)); + if (lesstif_attribute_dialog(opts, n, vals, "Export", NULL, NULL)) { + free(vals); + return 1; + } + printer->do_export(vals); + free(vals); + pcb_exporter = NULL; + return 0; +} + +/* ------------------------------------------------------------ */ + +static Widget sizes_dialog = 0; +static Widget sz_pcb_w, sz_pcb_h, sz_bloat, sz_shrink, sz_drc_wid, sz_drc_slk, sz_drc_drill, sz_drc_ring; +static Widget sz_text; +static Widget sz_set, sz_reset, sz_units; + +static int sz_str2val(Widget w, pcb_bool pcbu) +{ + char *buf = XmTextGetString(w); + if (!pcbu) + return strtol(buf, NULL, 0); + return pcb_get_value_ex(buf, NULL, NULL, NULL, conf_core.editor.grid_unit->suffix, NULL); +} + +static void sz_val2str(Widget w, pcb_coord_t u, int pcbu) +{ + static char buf[40]; + if (pcbu) + pcb_sprintf(buf, "%m+%.2mS", conf_core.editor.grid_unit->allow, u); + else + pcb_snprintf(buf, sizeof(buf), "%#mS %%", u); + XmTextSetString(w, buf); +} + +static void sizes_set() +{ + PCB->MaxWidth = sz_str2val(sz_pcb_w, 1); + PCB->MaxHeight = sz_str2val(sz_pcb_h, 1); + PCB->Bloat = sz_str2val(sz_bloat, 1); + PCB->Shrink = sz_str2val(sz_shrink, 1); + PCB->minWid = sz_str2val(sz_drc_wid, 1); + PCB->minSlk = sz_str2val(sz_drc_slk, 1); + PCB->minDrill = sz_str2val(sz_drc_drill, 1); + PCB->minRing = sz_str2val(sz_drc_ring, 1); +#warning think these over - are these only for new designs amd we keep real values in PCB-> ? + conf_set_design("design/text_scale", "%s", sz_text); + conf_set_design("design/bloat", "%s", sz_bloat); + conf_set_design("design/shrink", "%s", sz_shrink); + conf_set_design("design/min_wid", "%s", sz_drc_wid); + conf_set_design("design/min_slk", "%s", sz_drc_slk); + conf_set_design("design/min_drill", "%s", sz_drc_drill); + conf_set_design("design/min_ring", "%s", sz_drc_ring); + + pcb_crosshair_set_range(0, 0, PCB->MaxWidth, PCB->MaxHeight); + lesstif_pan_fixup(); +} + +void lesstif_sizes_reset() +{ + char *ls; + if (!sizes_dialog) + return; + sz_val2str(sz_pcb_w, PCB->MaxWidth, 1); + sz_val2str(sz_pcb_h, PCB->MaxHeight, 1); + sz_val2str(sz_bloat, PCB->Bloat, 1); + sz_val2str(sz_shrink, PCB->Shrink, 1); + sz_val2str(sz_drc_wid, PCB->minWid, 1); + sz_val2str(sz_drc_slk, PCB->minSlk, 1); + sz_val2str(sz_drc_drill, PCB->minDrill, 1); + sz_val2str(sz_drc_ring, PCB->minRing, 1); + sz_val2str(sz_text, conf_core.design.text_scale, 0); + + ls = pcb_strdup_printf(_("Units are %s."), conf_core.editor.grid_unit->in_suffix); + stdarg_n = 0; + stdarg(XmNlabelString, XmStringCreatePCB(ls)); + XtSetValues(sz_units, stdarg_args, stdarg_n); + free(ls); +} + +static Widget size_field(Widget parent, const char *label, int posn) +{ + Widget w, l; + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_POSITION); + stdarg(XmNtopPosition, posn); + stdarg(XmNbottomAttachment, XmATTACH_POSITION); + stdarg(XmNbottomPosition, posn + 1); + stdarg(XmNcolumns, 10); + w = XmCreateTextField(parent, XmStrCast("field"), stdarg_args, stdarg_n); + XtManageChild(w); + + stdarg_n = 0; + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_WIDGET); + stdarg(XmNrightWidget, w); + stdarg(XmNtopAttachment, XmATTACH_POSITION); + stdarg(XmNtopPosition, posn); + stdarg(XmNbottomAttachment, XmATTACH_POSITION); + stdarg(XmNbottomPosition, posn + 1); + stdarg(XmNlabelString, XmStringCreatePCB(label)); + stdarg(XmNalignment, XmALIGNMENT_END); + l = XmCreateLabel(parent, XmStrCast("label"), stdarg_args, stdarg_n); + XtManageChild(l); + + return w; +} + +static const char adjustsizes_syntax[] = "AdjustSizes()"; + +static const char adjustsizes_help[] = "Let the user change the board size, DRC parameters, etc"; + +/* %start-doc actions AdjustSizes + +Displays a dialog box that lets the user change the board +size, DRC parameters, and text scale. + +The units are determined by the default display units. + +%end-doc */ + +static int AdjustSizes(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (!sizes_dialog) { + Widget inf, sep; + + stdarg_n = 0; + stdarg(XmNmarginWidth, 3); + stdarg(XmNmarginHeight, 3); + stdarg(XmNhorizontalSpacing, 3); + stdarg(XmNverticalSpacing, 3); + stdarg(XmNautoUnmanage, False); + stdarg(XmNtitle, "Board Sizes"); + sizes_dialog = XmCreateFormDialog(mainwind, XmStrCast("sizes"), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + sz_reset = XmCreatePushButton(sizes_dialog, XmStrCast("Reset"), stdarg_args, stdarg_n); + XtManageChild(sz_reset); + XtAddCallback(sz_reset, XmNactivateCallback, (XtCallbackProc) lesstif_sizes_reset, 0); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_WIDGET); + stdarg(XmNrightWidget, sz_reset); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + sz_set = XmCreatePushButton(sizes_dialog, XmStrCast("Set"), stdarg_args, stdarg_n); + XtManageChild(sz_set); + XtAddCallback(sz_set, XmNactivateCallback, (XtCallbackProc) sizes_set, 0); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, sz_reset); + sep = XmCreateSeparator(sizes_dialog, XmStrCast("sep"), stdarg_args, stdarg_n); + XtManageChild(sep); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, sep); + sz_units = XmCreateLabel(sizes_dialog, XmStrCast("units"), stdarg_args, stdarg_n); + XtManageChild(sz_units); + + stdarg_n = 0; + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_WIDGET); + stdarg(XmNbottomWidget, sz_units); + stdarg(XmNfractionBase, 9); + inf = XmCreateForm(sizes_dialog, XmStrCast("sizes"), stdarg_args, stdarg_n); + XtManageChild(inf); + + sz_pcb_w = size_field(inf, "PCB Width", 0); + sz_pcb_h = size_field(inf, "PCB Height", 1); + sz_bloat = size_field(inf, "Bloat", 2); + sz_shrink = size_field(inf, "Shrink", 3); + sz_drc_wid = size_field(inf, "DRC Min Wid", 4); + sz_drc_slk = size_field(inf, "DRC Min Silk", 5); + sz_drc_drill = size_field(inf, "DRC Min Drill", 6); + sz_drc_ring = size_field(inf, "DRC Min Annular Ring", 7); + sz_text = size_field(inf, "Text Scale", 8); + } + lesstif_sizes_reset(); + XtManageChild(sizes_dialog); + return 0; +} + +/* ------------------------------------------------------------ */ + +void lesstif_update_layer_groups() +{ +#warning layer TODO: call a redraw on the edit group +} + +static const char editlayergroups_syntax[] = "EditLayerGroups()"; + +static const char editlayergroups_help[] = "Let the user change the layer groupings"; + +/* %start-doc actions EditLayerGroups + +Displays a dialog that lets the user view and change the layer +groupings. Each layer (row) can be a member of any one layer group +(column). Note the special layers @code{solder} and @code{component} +allow you to specify which groups represent the top and bottom of the +board. + +See @ref{ChangeName Action}. + +%end-doc */ + +extern void lesstif_show_layergrp_edit(void); +static int EditLayerGroups(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + lesstif_show_layergrp_edit(); + return 1; +} + + +static const char pcb_acts_fontsel[] = "EditLayerGroups()"; +static const char pcb_acth_fontsel[] = "Let the user change fonts"; +extern void lesstif_show_fontsel_edit(pcb_layer_t *txtly, pcb_text_t *txt, int type); +static int pcb_act_fontsel(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (argc > 1) + PCB_ACT_FAIL(fontsel); + + if (argc > 0) { + if (pcb_strcasecmp(argv[0], "Object") == 0) { + int type; + void *ptr1, *ptr2, *ptr3; + pcb_gui->get_coords(_("Select an Object"), &x, &y); + if ((type = pcb_search_screen(x, y, PCB_CHANGENAME_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { +/* pcb_undo_save_serial();*/ + lesstif_show_fontsel_edit(ptr1, ptr2, type); + } + } + else + PCB_ACT_FAIL(fontsel); + } + else + lesstif_show_fontsel_edit(NULL, NULL, 0); + return 0; +} + +/* ------------------------------------------------------------ */ + +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 (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; +} + +/* ------------------------------------------------------------ */ + +static const char importgui_syntax[] = "ImportGUI()"; + +static const char importgui_help[] = "Lets the user choose the schematics to import from"; + +/* %start-doc actions ImportGUI + +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. + +%end-doc */ + +static int ImportGUI(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + static int I_am_recursing = 0; + static XmString xms_sch = 0, xms_import = 0; + int rv; + XmString xmname; + char *name, *bname; + char *original_dir, *target_dir, *last_slash; + + if (I_am_recursing) + return 1; + + if (xms_sch == 0) + xms_sch = XmStringCreatePCB("*.sch"); + if (xms_import == 0) + xms_import = XmStringCreatePCB("Import from"); + + setup_fsb_dialog(); + + stdarg_n = 0; + stdarg(XmNtitle, "Import From"); + XtSetValues(XtParent(fsb), stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNpattern, xms_sch); + stdarg(XmNmustMatch, True); + stdarg(XmNselectionLabelString, xms_import); + XtSetValues(fsb, stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNdirectory, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &original_dir); + + if (!wait_for_dialog(fsb)) + return 1; + + stdarg_n = 0; + stdarg(XmNdirectory, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &target_dir); + + stdarg_n = 0; + stdarg(XmNdirSpec, &xmname); + XtGetValues(fsb, stdarg_args, stdarg_n); + + XmStringGetLtoR(xmname, XmFONTLIST_DEFAULT_TAG, &name); + + /* If the user didn't change directories, use just the base name. + This is the common case and means we don't have to get clever + about converting absolute paths into relative paths. */ + bname = name; + if (strcmp(original_dir, target_dir) == 0) { + last_slash = strrchr(name, '/'); + if (last_slash) + bname = last_slash + 1; + } + + pcb_attrib_put(PCB, "import::src0", bname); + + XtFree(name); + + + I_am_recursing = 1; + rv = pcb_hid_action("Import"); + I_am_recursing = 0; + + return rv; +} + +/* ------------------------------------------------------------ */ + +pcb_hid_action_t lesstif_dialog_action_list[] = { + {"Load", 0, Load, + load_help, load_syntax} + , + {"LoadVendor", 0, LoadVendor, + loadvendor_help, loadvendor_syntax} + , + {"Save", 0, Save, + save_help, save_syntax} + , + {"DoWindows", 0, DoWindows, + dowindows_help, dowindows_syntax} + , + {"PromptFor", 0, PromptFor, + promptfor_help, promptfor_syntax} + , + {"Confirm", 0, ConfirmAction} + , + {"About", 0, About, + about_help, about_syntax} + , + {"Print", 0, Print, + print_help, print_syntax} + , + {"PrintCalibrate", 0, PrintCalibrate, + printcalibrate_help, printcalibrate_syntax} + , + {"ExportGUI", 0, ExportGUI, + exportgui_help, exportgui_syntax} + , + {"AdjustSizes", 0, AdjustSizes, + adjustsizes_help, adjustsizes_syntax} + , + {"EditLayerGroups", 0, EditLayerGroups, + editlayergroups_help, editlayergroups_syntax} + , + {"FontSel", 0, pcb_act_fontsel, + pcb_acth_fontsel, pcb_acts_fontsel} + , + {"ImportGUI", 0, ImportGUI, + importgui_help, importgui_syntax} + , +}; + +PCB_REGISTER_ACTIONS(lesstif_dialog_action_list, lesstif_cookie) Index: tags/1.2.7/src_plugins/hid_lesstif/dlg_preview.c =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/dlg_preview.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/dlg_preview.c (revision 13657) @@ -0,0 +1,373 @@ +/* Directly included by main.c for now */ + +static int widget_depth(Widget w) { + Arg args[1]; + int depth; + + XtSetArg(args[0], XtNdepth, &depth); + XtGetValues(w, args, 1); + return depth; +} + +#define SHOW_SAVES \ + int save_vx, save_vy, save_vw, save_vh; \ + int save_fx, save_fy; \ + double save_vz; \ + Pixmap save_px, save_main_px, save_mask_px, save_mask_bm + +/* saving flip setting in this macro is required to properly calculate coordinates of an event (Px, Py functions) */ +#define SHOW_ENTER \ +do { \ + pinout = 0; \ + save_vx = view_left_x; \ + save_vy = view_top_y; \ + save_vz = view_zoom; \ + save_vw = view_width; \ + save_vh = view_height; \ + save_fx = conf_core.editor.view.flip_x; \ + save_fy = conf_core.editor.view.flip_y; \ + save_px = pixmap; \ + save_main_px = main_pixmap; \ + save_mask_px = mask_pixmap; \ + save_mask_bm = mask_bitmap; \ + main_pixmap = XCreatePixmap(XtDisplay(da), XtWindow(da), pd->v_width, pd->v_height, widget_depth(da)); \ + mask_pixmap = XCreatePixmap(XtDisplay(da), XtWindow(da), pd->v_width, pd->v_height, widget_depth(da)); \ + mask_bitmap = XCreatePixmap(XtDisplay(da), XtWindow(da), pd->v_width, pd->v_height, 1); \ + pixmap = main_pixmap; \ + view_left_x = pd->x; \ + view_top_y = pd->y; \ + view_zoom = pd->zoom; \ + view_width = pd->v_width; \ + view_height = pd->v_height; \ + conf_force_set_bool(conf_core.editor.view.flip_x, 0); \ + conf_force_set_bool(conf_core.editor.view.flip_y, 0); \ +} while(0) + +#define SHOW_LEAVE \ +do { \ + view_left_x = save_vx; \ + view_top_y = save_vy; \ + view_zoom = save_vz; \ + view_width = save_vw; \ + view_height = save_vh; \ + XFreePixmap(lesstif_display, main_pixmap); \ + XFreePixmap(lesstif_display, mask_pixmap); \ + XFreePixmap(lesstif_display, mask_bitmap); \ + main_pixmap = save_main_px; \ + mask_pixmap = save_mask_px; \ + mask_bitmap = save_mask_bm; \ + pixmap = save_px; \ + conf_force_set_bool(conf_core.editor.view.flip_x, save_fx); \ + conf_force_set_bool(conf_core.editor.view.flip_y, save_fy); \ +} while(0) + +#define SHOW_DRAW \ +do { \ + XGCValues gcv; \ + GC gc; \ + memset(&gcv, 0, sizeof(gcv)); \ + gcv.graphics_exposures = 0; \ + gc = XtGetGC(da, GCGraphicsExposures, &gcv); \ + XSetForeground(display, bg_gc, bgcolor); \ + XFillRectangle(display, pixmap, bg_gc, 0, 0, pd->v_width, pd->v_height); \ + pcb_hid_expose_layer(&lesstif_hid, &pd->ctx); \ + XCopyArea(lesstif_display, pixmap, XtWindow(da), gc, 0, 0, pd->v_width, pd->v_height, 0, 0); \ + XtReleaseGC(da, gc); \ +} while(0) + +static void show_layer_callback(Widget da, PreviewData * pd, XmDrawingAreaCallbackStruct * cbs) +{ + SHOW_SAVES; + int reason = cbs ? cbs->reason : 0; + + if (pd->window == 0 && reason == XmCR_RESIZE) + return; + if (pd->window == 0 || reason == XmCR_RESIZE) { + Dimension w, h; + double z; + + stdarg_n = 0; + stdarg(XmNwidth, &w); + stdarg(XmNheight, &h); + XtGetValues(da, stdarg_args, stdarg_n); + + pd->window = XtWindow(da); + pd->v_width = w; + pd->v_height = h; + pd->zoom = (pd->right - pd->left + 1) / (double) w; + z = (pd->bottom - pd->top + 1) / (double) h; + if (pd->zoom < z) + pd->zoom = z; + + pd->x = (pd->left + pd->right) / 2 - pd->v_width * pd->zoom / 2; + pd->y = (pd->top + pd->bottom) / 2 - pd->v_height * pd->zoom / 2; + } + + SHOW_ENTER; + SHOW_DRAW; + + SHOW_LEAVE; + +} + +static void show_layer_inp_callback(Widget da, PreviewData * pd, XmDrawingAreaCallbackStruct * cbs) +{ + SHOW_SAVES; + pcb_coord_t cx, cy; + pcb_hid_cfg_mod_t btn; + pcb_hid_mouse_ev_t kind; + + SHOW_ENTER; + + btn = lesstif_mb2cfg(cbs->event->xbutton.button); + + cx = Px(cbs->event->xbutton.x); + cy = Py(cbs->event->xbutton.y); + +/* pcb_printf("ev %d;%d %$mm;%$mm %x\n", cbs->event->xbutton.x, cbs->event->xbutton.y, cx, cy, btn);*/ + + kind = -1; + if (cbs->event->type == ButtonPress) kind = PCB_HID_MOUSE_PRESS; + if (cbs->event->type == ButtonRelease) kind = PCB_HID_MOUSE_RELEASE; + + switch(btn) { + case PCB_MB_LEFT: + if (pd->mouse_ev != NULL) + if (pd->mouse_ev(da, kind, cx, cy)) + SHOW_DRAW; + break; + case PCB_MB_RIGHT: + if (pd->mouse_ev != NULL) + if (pd->mouse_ev(da, PCB_HID_MOUSE_POPUP, cx, cy)) + SHOW_DRAW; + break; + case PCB_MB_MIDDLE: + if (kind == PCB_HID_MOUSE_PRESS) { + pd->pan = 1; + pd->pan_ox = cbs->event->xbutton.x; + pd->pan_oy = cbs->event->xbutton.y; + pd->pan_opx = view_left_x; + pd->pan_opy = view_top_y; + } + else if (kind == PCB_HID_MOUSE_RELEASE) + pd->pan = 0; + break; + case PCB_MB_SCROLL_DOWN: + pd->zoom *= 1.25; + view_zoom = pd->zoom; + SHOW_DRAW; + break; + case PCB_MB_SCROLL_UP: + pd->zoom *= 0.8; + view_zoom = pd->zoom; + SHOW_DRAW; + break; + default:; + } + + SHOW_LEAVE; +} + +static void show_layer_mot_callback(Widget w, XtPointer pd_, XEvent * e, Boolean * ctd) +{ + Widget da = w; + PreviewData *pd = pd_; + SHOW_SAVES; + Window root, child; + unsigned int keys_buttons; + int root_x, root_y, pos_x, pos_y; + pcb_coord_t cx, cy; + + while (XCheckMaskEvent(display, PointerMotionMask, e)); + XQueryPointer(display, e->xmotion.window, &root, &child, &root_x, &root_y, &pos_x, &pos_y, &keys_buttons); + + SHOW_ENTER; + + cx = Px(pos_x); + cy = Py(pos_y); + +/* pcb_printf("mo %d;%d %$mm;%$mm\n", pos_x, pos_y, cx, cy);*/ + if (pd->pan) { +/* pcb_coord_t ol = pd->x, ot = pd->y;*/ + pd->x = pd->pan_opx - (pos_x - pd->pan_ox) * view_zoom; + pd->y = pd->pan_opy - (pos_y - pd->pan_oy) * view_zoom; +/* pd->view_right += ol - pd->view_left_x; + pd->view_bottom += ot - pd->view_top_y;*/ + SHOW_DRAW; + } + else if (pd->mouse_ev != NULL) { + pd->mouse_ev(w, PCB_HID_MOUSE_MOTION, cx, cy); + SHOW_DRAW; + } + + SHOW_LEAVE; +} + + +static void show_layer_unmap(Widget w, PreviewData * pd, void *v) +{ + if (pd->pre_close != NULL) + pd->pre_close(pd); + XtDestroyWidget(XtParent(pd->form)); + free(pd); +} + + +static PreviewData *lesstif_show_layer(pcb_layer_id_t layer, const char *title, int modal) +{ + double scale; + Widget da; + PreviewData *pd; + + if (!mainwind) + return NULL; + + pd = (PreviewData *) calloc(1, sizeof(PreviewData)); + + pd->ctx.content.layer_id = layer; + + pd->ctx.view.X1 = pd->left = 0; + pd->ctx.view.X2 = pd->right = PCB_MM_TO_COORD(130); + pd->ctx.view.Y1 = pd->top = 0; + pd->ctx.view.Y2 = pd->bottom = PCB_MM_TO_COORD(130); + pd->ctx.force = 1; + + pd->prev = 0; + pd->zoom = 0; + + stdarg_n = 0; + pd->form = XmCreateFormDialog(mainwind, XmStrCast(title), stdarg_args, stdarg_n); + pd->window = 0; + XtAddCallback(pd->form, XmNunmapCallback, (XtCallbackProc) show_layer_unmap, (XtPointer) pd); + + if (modal) + XtVaSetValues(pd->form, XmNdialogStyle, XmDIALOG_PRIMARY_APPLICATION_MODAL, NULL); + + scale = sqrt(200.0 * 200.0 / ((pd->right - pd->left + 1.0) * (pd->bottom - pd->top + 1.0))); + + stdarg_n = 0; + stdarg(XmNwidth, (int) (scale * (pd->right - pd->left + 1))); + stdarg(XmNheight, (int) (scale * (pd->bottom - pd->top + 1))); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + da = XmCreateDrawingArea(pd->form, XmStrCast(title), stdarg_args, stdarg_n); + XtManageChild(da); + + XtAddCallback(da, XmNexposeCallback, (XtCallbackProc) show_layer_callback, (XtPointer) pd); + XtAddCallback(da, XmNresizeCallback, (XtCallbackProc) show_layer_callback, (XtPointer) pd); + XtAddCallback(da, XmNinputCallback, (XtCallbackProc) show_layer_inp_callback, (XtPointer) pd); + + XtAddEventHandler(da, + PointerMotionMask | PointerMotionHintMask | EnterWindowMask | LeaveWindowMask, + 0, show_layer_mot_callback, pd); + + XtManageChild(pd->form); + + return pd; +} + +/***************** instance for layer group edit **********************/ + +#include "stub_draw.h" + +static PreviewData *layergrp_edit = NULL; + +static void layergrp_pre_close(struct PreviewData *pd) +{ + if (pd == layergrp_edit) + layergrp_edit = NULL; +} + +void lesstif_show_layergrp_edit(void) +{ + pcb_layer_id_t lid; + if (layergrp_edit != NULL) + return; + if (pcb_layer_list(PCB, PCB_LYT_CSECT, &lid, 1) > 0) { + layergrp_edit = lesstif_show_layer(lid, "Layer groups", 0); + layergrp_edit->mouse_ev = pcb_stub_draw_csect_mouse_ev; + layergrp_edit->pre_close = layergrp_pre_close; + } +} + +/***************** instance for font selection **********************/ + +#include "stub_draw.h" + +static PreviewData *fontsel_glob = NULL; + +static void fontsel_pre_close_glob(struct PreviewData *pd) +{ + if (pd == fontsel_glob) + fontsel_glob = NULL; +} + +static void lesstif_show_fontsel_global() +{ + pcb_layer_id_t lid; + if (fontsel_glob != NULL) + return; + if (pcb_layer_list(PCB, PCB_LYT_DIALOG, &lid, 1) > 0) { + fontsel_glob = lesstif_show_layer(lid, "Pen font selection", 0); + fontsel_glob->ctx.dialog_draw = pcb_stub_draw_fontsel; + fontsel_glob->mouse_ev = pcb_stub_draw_fontsel_mouse_ev; + fontsel_glob->overlay_draw = NULL; + fontsel_glob->pre_close = fontsel_pre_close_glob; + } +} + + +static PreviewData *fontsel_loc = NULL; + + +static void fontsel_pre_close_loc(struct PreviewData *pd) +{ + if (pd == fontsel_loc) + fontsel_loc = NULL; +} + +static void lesstif_show_fontsel_local(pcb_layer_t *txtly, pcb_text_t *txt, int type) +{ + pcb_layer_id_t lid; + pcb_text_t *old_txt; + pcb_layer_t *old_layer; + int old_type; + + if (pcb_layer_list(PCB, PCB_LYT_DIALOG, &lid, 1) <= 0) + return; + + old_txt = *pcb_stub_draw_fontsel_text_obj; + old_layer = *pcb_stub_draw_fontsel_layer_obj; + old_type = *pcb_stub_draw_fontsel_text_type; + + *pcb_stub_draw_fontsel_text_obj = txt; + *pcb_stub_draw_fontsel_layer_obj = txtly; + *pcb_stub_draw_fontsel_text_type = type; + + fontsel_loc = lesstif_show_layer(lid, "Change font of text object", 1); + fontsel_loc->mouse_ev = pcb_stub_draw_fontsel_mouse_ev; + fontsel_loc->overlay_draw = NULL; + fontsel_loc->pre_close = fontsel_pre_close_loc; + + + while (fontsel_loc != NULL) { + XEvent e; + XtAppNextEvent(app_context, &e); + XtDispatchEvent(&e); + } + + *pcb_stub_draw_fontsel_text_obj = old_txt; + *pcb_stub_draw_fontsel_layer_obj = old_layer; + *pcb_stub_draw_fontsel_text_type = old_type; +} + +void lesstif_show_fontsel_edit(pcb_layer_t *txtly, pcb_text_t *txt, int type) +{ + if (txt == NULL) + lesstif_show_fontsel_global(); + else + lesstif_show_fontsel_local(txtly, txt, type); +} + Index: tags/1.2.7/src_plugins/hid_lesstif/hid_lesstif.pup =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/hid_lesstif.pup (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/hid_lesstif.pup (revision 13657) @@ -0,0 +1,10 @@ +$class hid +$short the lesstif gui +$long GUI: the lesstif HID. +$state works +default buildin +dep draw_csect +dep draw_fontsel +dep lib_hid_common +dep dialogs +autoload 1 Index: tags/1.2.7/src_plugins/hid_lesstif/lesstif.h =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/lesstif.h (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/lesstif.h (revision 13657) @@ -0,0 +1,87 @@ +#include "hid_cfg_input.h" +#include "compat_nls.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(void); +extern int lesstif_call_action(const char *, int, char **); +extern void lesstif_sizes_reset(void); +extern void lesstif_pan_fixup(void); +extern void lesstif_show_library(void); +extern void lesstif_show_netlist(void); +extern Pixel lesstif_parse_color(const char *value); +extern void lesstif_insert_style_buttons(Widget menu); +extern void lesstif_styles_update_values(); +extern void lesstif_update_layer_groups(); +extern void lesstif_update_status_line(); +extern char *lesstif_prompt_for(const char *, const char *); +extern char *lesstif_fileselect(const char *, const char *, const char *, const char *, const char *, int); +extern void lesstif_log(const char *fmt, ...); +extern void lesstif_attributes_dialog(const char *, pcb_attribute_list_t *); + + +#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) +{ + if (x && x[0]) + x = gettext(x); + return XmStringCreateLtoR(XmStrCast(x), XmFONTLIST_DEFAULT_TAG); +} + +extern const char *lesstif_cookie; Index: tags/1.2.7/src_plugins/hid_lesstif/library.c =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/library.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/library.c (revision 13657) @@ -0,0 +1,190 @@ +#include "xincludes.h" + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include + +#include "compat_misc.h" +#include "data.h" +#include "buffer.h" +#include +#include "plug_footprint.h" + +#include "hid.h" +#include "lesstif.h" +#include "stdarg.h" +#include "event.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_element_load_to_buffer(PCB_PASTEBUFFER, e->data.fp.loc_info)) + pcb_crosshair_set_mode(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 libraryshow_syntax[] = "LibraryShow()"; + +static const char libraryshow_help[] = "Displays the library window."; + +/* %start-doc actions LibraryShow + +%end-doc */ + +static int LibraryShow(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + if (build_library_dialog()) + return 0; + return 0; +} + +void lesstif_show_library() +{ + if (mainwind) { + if (!library_dialog) + LesstifLibraryChanged(0, 0, 0); + XtManageChild(library_dialog); + } +} + +pcb_hid_action_t lesstif_library_action_list[] = { + {"LibraryShow", 0, LibraryShow, + libraryshow_help, libraryshow_syntax} + , +}; + +PCB_REGISTER_ACTIONS(lesstif_library_action_list, lesstif_cookie) Index: tags/1.2.7/src_plugins/hid_lesstif/main.c =================================================================== --- tags/1.2.7/src_plugins/hid_lesstif/main.c (nonexistent) +++ tags/1.2.7/src_plugins/hid_lesstif/main.c (revision 13657) @@ -0,0 +1,3869 @@ +/* 15 Oct 2008 Ineiev: add different crosshair shapes */ + +#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 "action_helper.h" +#include "crosshair.h" +#include "layer.h" +#include "pcb-printf.h" +#include "clip.h" +#include "event.h" +#include "error.h" +#include "plugins.h" +#include "safe_fs.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_helper.h" +#include "hid_init.h" +#include "hid_color.h" +#include "hid_extents.h" +#include "hid_flags.h" +#include "hid_actions.h" +#include "stdarg.h" +#include "misc_util.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "layer_vis.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; + +#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_hid_t *me_pointer; + Pixel color; + char *colorname; + int width; + pcb_cap_style_t cap; + char xor_set; + char erase; +} hid_gc_s; + +static 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; + +/* These are for the pinout windows. */ +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, 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; + +/* Linked list of all pinout windows. */ +static PreviewData *pinouts = 0; +/* If set, we are currently updating this pinout window. */ +static PreviewData *pinout = 0; + +static int 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 int 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 + +/* %start-doc options "22 lesstif GUI Options" +@ftable @code +@item --pcb-menu +Location of the @file{pcb-menu.res} file which defines the menu for the lesstif GUI. +@end ftable +%end-doc +*/ +#warning TODO#1: this should be generic and not depend on the HID +/* + {"pcb-menu", "Location of pcb-menu.res file", + PCB_HATT_STRING, 0, 0, {0, PCBSHAREDIR "/pcb-menu.res", 0}, 0, &lesstif_pcbmenu_path} +#define HA_pcbmenu 3 +*/ +}; + +PCB_REGISTER_ATTRIBUTES(lesstif_attribute_list, lesstif_cookie) + +static pcb_composite_op_t lesstif_drawing_mode = 0; +#define use_mask() ((lesstif_drawing_mode == PCB_HID_COMP_POSITIVE) || (lesstif_drawing_mode == PCB_HID_COMP_NEGATIVE)) + +static void zoom_max(); +static void zoom_to(double factor, int x, int y); +static void zoom_by(double factor, int x, int y); +static void zoom_toggle(int x, int y); +static void pinout_callback(Widget, PreviewData *, XmDrawingAreaCallbackStruct *); +static void pinout_unmap(Widget, PreviewData *, void *); +static void Pan(int mode, int x, int 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 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 LesstifLayersChanged(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); + LesstifLayersChanged(NULL, 0, NULL); + LesstifRouteStylesChanged(NULL, 0, NULL); + lesstif_sizes_reset(); + lesstif_update_layer_groups(); + while (pinouts) + pinout_unmap(0, pinouts, 0); + 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 setunits_syntax[] = "SetUnits(mm|mil)"; + +static const char setunits_help[] = "Set the default measurement units."; + +/* %start-doc actions SetUnits + +@table @code + +@item mil +Sets the display units to mils (1/1000 inch). + +@item mm +Sets the display units to millimeters. + +@end table + +%end-doc */ + +static int SetUnits(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const pcb_unit_t *new_unit; + if (argc == 0) + return 0; + new_unit = get_unit_struct(argv[0]); + if (new_unit != NULL && new_unit->allow != PCB_UNIT_NO_PRINT) { + conf_set(CFR_DESIGN, "editor/grid_unit", -1, argv[0], POL_OVERWRITE); +#warning TODO: figure what to do with increments +#if 0 + Settings.increments = pcb_get_increments_struct(Settings.grid_unit->suffix); +#endif + pcb_attrib_put(PCB, "PCB::grid::unit", argv[0]); + } + lesstif_sizes_reset(); + lesstif_styles_update_values(); + return 0; +} + +static const char zoom_syntax[] = "Zoom()\n" "Zoom(factor)"; + +static const char zoom_help[] = "Various zoom factor changes."; + +/* %start-doc actions Zoom + +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, +@var{factor} specifies a change in zoom factor. It may be prefixed by +@code{+}, @code{-}, or @code{=} to change how the zoom factor is +modified. The @var{factor} is a floating point number, such as +@code{1.5} or @code{0.75}. + +@table @code + +@item +@var{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. + +@item -@var{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. + +@item =@var{factor} + +The @var{factor} is an absolute zoom factor; the unit for this value +is "PCB units per screen pixel". Since PCB units are 0.01 mil, a +@var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, +about the actual resolution of most screens - resulting in an "actual +size" board. Similarly, a @var{factor} of 100 gives you a 10x actual +size. + +@end table + +Note that zoom factors of zero are silently ignored. + +%end-doc */ + +static int ZoomAction(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + const char *vp; + double v; + if (x == 0 && y == 0) { + x = view_width / 2; + y = view_height / 2; + } + else { + x = Vx(x); + y = Vy(y); + } + if (argc < 1) { + zoom_max(); + return 0; + } + vp = argv[0]; + if (pcb_strcasecmp(vp, "toggle") == 0) { + zoom_toggle(x, y); + return 0; + } + if (*vp == '+' || *vp == '-' || *vp == '=') + vp++; + pcb_setlocale(LC_ALL, "C"); + v = strtod(vp, NULL); + pcb_setlocale(LC_ALL, ""); + if (v <= 0) + return 1; + switch (argv[0][0]) { + case '-': + zoom_by(1 / v, x, y); + break; + default: + case '+': + zoom_by(v, x, y); + break; + case '=': + zoom_to(v, x, y); + break; + } + return 0; +} + +static int pan_thumb_mode; + +static int PanAction(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + int mode; + + if (argc == 2) { + pan_thumb_mode = (pcb_strcasecmp(argv[0], "thumb") == 0) ? 1 : 0; + mode = atoi(argv[1]); + } + else { + pan_thumb_mode = 0; + mode = atoi(argv[0]); + } + Pan(mode, Vx(x), Vy(y)); + + return 0; +} + +static const char swapsides_syntax[] = "SwapSides(|v|h|r)"; + +static const char swapsides_help[] = "Swaps the side of the board you're looking at."; + +/* %start-doc actions SwapSides + +This action changes the way you view the board. + +@table @code + +@item v +Flips the board over vertically (up/down). + +@item h +Flips the board over horizontally (left/right), like flipping pages in +a book. + +@item r +Rotates the board 180 degrees without changing sides. + +@end table + +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. + +As a special case, 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. + +%end-doc */ +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; +} + +#warning TODO: ui_zoomplan.c does the same, maybe make the code common? +static int SwapSides(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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; + + 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); + + if (argc > 0) { + switch (argv[0][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; + } + /* 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(); + return 0; +} + +static Widget m_cmd = 0, m_cmd_label; + +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_hid_parse_command(s); + XtFree(s); + XmTextSetString(w, XmStrCast("")); + case XmCR_LOSING_FOCUS: + XtUnmanageChild(m_cmd); + XtUnmanageChild(m_cmd_label); + break; + } +} + +static void command_event_handler(Widget w, XtPointer p, XEvent * e, Boolean * cont) +{ + char buf[10]; + KeySym sym; + + switch (e->type) { + case KeyPress: + XLookupString((XKeyEvent *) e, buf, sizeof(buf), &sym, NULL); + switch (sym) { + case XK_Escape: + XtUnmanageChild(m_cmd); + XtUnmanageChild(m_cmd_label); + XmTextSetString(w, XmStrCast("")); + *cont = False; + break; + } + break; + } +} + +static const char command_syntax[] = "Command()"; + +static const char command_help[] = "Displays the command line input window."; + +/* %start-doc actions Command + +The command window allows the user to manually enter actions to be +executed. Action syntax can be done one of two ways: + +@table @code + +@item +Follow the action name by an open parenthesis, arguments separated by +commas, end with a close parenthesis. Example: @code{Abc(1,2,3)} + +@item +Separate the action name and arguments by spaces. Example: @code{Abc +1 2 3}. + +@end table + +The first option allows you to have arguments with spaces in them, +but the second is more ``natural'' to type for most people. + +Note that action names are not case sensitive, but arguments normally +are. However, most actions will check for ``keywords'' in a case +insensitive way. + +There are three ways to finish with the command window. If you press +the @code{Enter} key, the command is invoked, the window goes away, +and the next time you bring up the command window it's empty. If you +press the @code{Esc} key, the window goes away without invoking +anything, and the next time you bring up the command window it's +empty. If you change focus away from the command window (i.e. click +on some other window), the command window goes away but the next time +you bring it up it resumes entering the command you were entering +before. + +%end-doc */ + +static int Command(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + XtManageChild(m_cmd_label); + XtManageChild(m_cmd); + XmProcessTraversal(m_cmd, XmTRAVERSE_CURRENT); + return 0; +} + +static const char benchmark_syntax[] = "Benchmark()"; + +static const char benchmark_help[] = "Benchmark the GUI speed."; + +/* %start-doc actions Benchmark + +This action is used to speed-test the Lesstif graphics subsystem. 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. + +%end-doc */ + +static int Benchmark(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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); + XSync(display, 0); + time(&end); + i++; + } + while (end - start < 10); + + printf("%g redraws per second\n", i / 10.0); + + main_pixmap = save_main; + return 0; +} + +static int Center(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + 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(); + /* Move the pointer to the center of the window, but only if it's + currently within the window already. Watch out for edges, + though. */ + XWarpPointer(display, window, window, 0, 0, view_width, view_height, Vx(x), Vy(y)); + return 0; +} + +pcb_hid_action_t lesstif_main_action_list[] = { + {"SetUnits", 0, SetUnits, + setunits_help, setunits_syntax} + , + {"Zoom", "Click on a place to zoom in", ZoomAction, + zoom_help, zoom_syntax} + , + {"Pan", "Click on a place to pan", PanAction, + zoom_help, zoom_syntax} + , + {"SwapSides", 0, SwapSides, + swapsides_help, swapsides_syntax} + , + {"Command", 0, Command, + command_help, command_syntax} + , + {"Benchmark", 0, Benchmark, + benchmark_help, benchmark_syntax} + , + {"Center", "Click on a location to center", 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) +{ + *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) +{ + 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, int x, int y) +{ + double max_zoom, xfrac, yfrac; + int 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_toggle(int x, int y) +{ + double tmp; + + tmp = prev_view_zoom; + prev_view_zoom = view_zoom; + zoom_to(tmp, x, y); +} + +void zoom_by(double factor, int x, int y) +{ + zoom_to(view_zoom * factor, x, y); +} + +static int panning = 0; +static int shift_pressed; +static int ctrl_pressed; +static int alt_pressed; + +/* X and Y are in screen coordinates. */ +static void Pan(int mode, int x, int y) +{ + static int ox, oy; + static int 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) +{ + 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. */ + 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_adjust_attached_objects(); + pcb_notify_crosshair_change(pcb_true); + in_move_event = 0; +} + +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); + + 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); + 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; + 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_idle_proc(); + break; + + default: + printf("work_area: unknown event %d\n", e->type); + break; + } +} + +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("#804000"); + XSetForeground(display, arc1_gc, c); + arc2_gc = XCreateGC(display, window, 0, 0); + c = lesstif_parse_color("#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) { + XRenderPictureAttributes pa; + XRenderColor a = { 0, 0, 0, 0x8000 }; + + 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) +{ +#warning 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; +} + + +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; + + 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