Index: tags/1.2.3/AUTHORS =================================================================== --- tags/1.2.3/AUTHORS (nonexistent) +++ tags/1.2.3/AUTHORS (revision 8969) @@ -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.3/COPYING =================================================================== --- tags/1.2.3/COPYING (nonexistent) +++ tags/1.2.3/COPYING (revision 8969) @@ -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.3/Changelog =================================================================== --- tags/1.2.3/Changelog (nonexistent) +++ tags/1.2.3/Changelog (revision 8969) @@ -0,0 +1,1254 @@ +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.3/INSTALL =================================================================== --- tags/1.2.3/INSTALL (nonexistent) +++ tags/1.2.3/INSTALL (revision 8969) @@ -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.3/Makefile =================================================================== --- tags/1.2.3/Makefile (nonexistent) +++ tags/1.2.3/Makefile (revision 8969) @@ -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.3/Makefile.conf.in =================================================================== --- tags/1.2.3/Makefile.conf.in (nonexistent) +++ tags/1.2.3/Makefile.conf.in (revision 8969) @@ -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.3/README =================================================================== --- tags/1.2.3/README (nonexistent) +++ tags/1.2.3/README (revision 8969) @@ -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.3/Release_notes =================================================================== --- tags/1.2.3/Release_notes (nonexistent) +++ tags/1.2.3/Release_notes (revision 8969) @@ -0,0 +1,20 @@ +pcb-rnd 1.2.3 +~~~~~~~~~~~~~ + +Among the usual bugfixes, the following major features have been added: + +1. Plugin system rewrite; the original system, mostly consisting of code +inherited from mainline, was unable to handle plugin-plugin dependencies, +couldn't distinguish between "available" and "should load". Switched over +the whole plugin system to puplug. + +2. Editable mask and paste layers, using positive/negative, auto/manual +compositing layers. Silk layers can be composite too, with manual-negative +layers removing auto silk generated by elements. (Not yet available with +opengl rendering.) + +3. Gtk: new layer selector widget in top window and cross-section view +upgrades to expose the new composite layer features of the editable layers. + +4. eagle board import - special thanks to LA3PNA (Thomas S. Knutsen) for +supporting the implementation Index: tags/1.2.3/config.h.in =================================================================== --- tags/1.2.3/config.h.in (nonexistent) +++ tags/1.2.3/config.h.in (revision 8969) @@ -0,0 +1,232 @@ +print [@ /***** Generated by scconfig - DO NOT EDIT *****/ + +/* Source: config.h.in; to regenerate run ./configure */ + +#ifndef PCB_CONFIG_H +#define PCB_CONFIG_H + +/****************************************************************************/ +/* Static defines to enable extra features on some systems; once we get + testers on those systems, we can remove them and see if scconfig figured + everything. */ + +/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# define _ALL_SOURCE 1 +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# define _POSIX_PTHREAD_SEMANTICS 1 +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# define _TANDEM_SOURCE 1 +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif + +/****************************************************************************/ +/* Package properties */ + +/* Name of package */ +#define PCB_PACKAGE "pcb" + +/* Name of this program's gettext domain */ +#define GETTEXT_PACKAGE "pcb" + +/****************************************************************************/ +/* These ones are already autodetected by scconfig */ +@] + +print {\n\n/* Macro to add a funciton attribute to suppress "function unused" for static inline functions declared in .h files */\n} +print_ternary ?cc/func_attr/unused/presents {#define PCB_FUNC_UNUSED __attribute__((unused))} {#define PCB_FUNC_UNUSED} + +print {\n\n/* Wether setenv() works */\n} +print_ternary ?libs/env/setenv/presents {#define PCB_HAVE_SETENV 1} {/* #undef PCB_HAVE_SETENV */} + +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 +# 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 +#endif + + +#endif +@] Index: tags/1.2.3/configure =================================================================== --- tags/1.2.3/configure (nonexistent) +++ tags/1.2.3/configure (revision 8969) @@ -0,0 +1,4 @@ +#!/bin/sh +cd scconfig +make +./configure "$@" Property changes on: tags/1.2.3/configure ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/data/Makefile =================================================================== --- tags/1.2.3/data/Makefile (nonexistent) +++ tags/1.2.3/data/Makefile (revision 8969) @@ -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.3/data/README =================================================================== --- tags/1.2.3/data/README (nonexistent) +++ tags/1.2.3/data/README (revision 8969) @@ -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.3/data/application-x-excellon-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-excellon-16.png =================================================================== --- tags/1.2.3/data/application-x-excellon-16.png (nonexistent) +++ tags/1.2.3/data/application-x-excellon-16.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-excellon-16.svg =================================================================== --- tags/1.2.3/data/application-x-excellon-16.svg (nonexistent) +++ tags/1.2.3/data/application-x-excellon-16.svg (revision 8969) @@ -0,0 +1,1271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-excellon-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-excellon-22.png =================================================================== --- tags/1.2.3/data/application-x-excellon-22.png (nonexistent) +++ tags/1.2.3/data/application-x-excellon-22.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-excellon-22.svg =================================================================== --- tags/1.2.3/data/application-x-excellon-22.svg (nonexistent) +++ tags/1.2.3/data/application-x-excellon-22.svg (revision 8969) @@ -0,0 +1,1571 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-excellon-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-excellon-24.png =================================================================== --- tags/1.2.3/data/application-x-excellon-24.png (nonexistent) +++ tags/1.2.3/data/application-x-excellon-24.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-excellon-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-excellon-32.png =================================================================== --- tags/1.2.3/data/application-x-excellon-32.png (nonexistent) +++ tags/1.2.3/data/application-x-excellon-32.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-excellon-32.svg =================================================================== --- tags/1.2.3/data/application-x-excellon-32.svg (nonexistent) +++ tags/1.2.3/data/application-x-excellon-32.svg (revision 8969) @@ -0,0 +1,1406 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-excellon-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-excellon-48.png =================================================================== --- tags/1.2.3/data/application-x-excellon-48.png (nonexistent) +++ tags/1.2.3/data/application-x-excellon-48.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-excellon-48.svg =================================================================== --- tags/1.2.3/data/application-x-excellon-48.svg (nonexistent) +++ tags/1.2.3/data/application-x-excellon-48.svg (revision 8969) @@ -0,0 +1,1283 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-excellon.svg =================================================================== --- tags/1.2.3/data/application-x-excellon.svg (nonexistent) +++ tags/1.2.3/data/application-x-excellon.svg (revision 8969) @@ -0,0 +1,1289 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Excellon file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-gerber-16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-gerber-16.png =================================================================== --- tags/1.2.3/data/application-x-gerber-16.png (nonexistent) +++ tags/1.2.3/data/application-x-gerber-16.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-gerber-16.svg =================================================================== --- tags/1.2.3/data/application-x-gerber-16.svg (nonexistent) +++ tags/1.2.3/data/application-x-gerber-16.svg (revision 8969) @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-gerber-22.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-gerber-22.png =================================================================== --- tags/1.2.3/data/application-x-gerber-22.png (nonexistent) +++ tags/1.2.3/data/application-x-gerber-22.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-gerber-22.svg =================================================================== --- tags/1.2.3/data/application-x-gerber-22.svg (nonexistent) +++ tags/1.2.3/data/application-x-gerber-22.svg (revision 8969) @@ -0,0 +1,608 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-gerber-24.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-gerber-24.png =================================================================== --- tags/1.2.3/data/application-x-gerber-24.png (nonexistent) +++ tags/1.2.3/data/application-x-gerber-24.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-gerber-32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-gerber-32.png =================================================================== --- tags/1.2.3/data/application-x-gerber-32.png (nonexistent) +++ tags/1.2.3/data/application-x-gerber-32.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-gerber-32.svg =================================================================== --- tags/1.2.3/data/application-x-gerber-32.svg (nonexistent) +++ tags/1.2.3/data/application-x-gerber-32.svg (revision 8969) @@ -0,0 +1,544 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-gerber-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/application-x-gerber-48.png =================================================================== --- tags/1.2.3/data/application-x-gerber-48.png (nonexistent) +++ tags/1.2.3/data/application-x-gerber-48.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-gerber-48.svg =================================================================== --- tags/1.2.3/data/application-x-gerber-48.svg (nonexistent) +++ tags/1.2.3/data/application-x-gerber-48.svg (revision 8969) @@ -0,0 +1,707 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-gerber.svg =================================================================== --- tags/1.2.3/data/application-x-gerber.svg (nonexistent) +++ tags/1.2.3/data/application-x-gerber.svg (revision 8969) @@ -0,0 +1,712 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Gerber file + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-footprint-16.png =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-16.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-16.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-footprint-16.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-16.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-16.svg (revision 8969) @@ -0,0 +1,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-footprint-22.png =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-22.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-22.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-footprint-22.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-22.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-22.svg (revision 8969) @@ -0,0 +1,573 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-footprint-24.png =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-24.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-24.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/data/application-x-pcb-footprint-32.png =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-32.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-32.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-footprint-32.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-32.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-32.svg (revision 8969) @@ -0,0 +1,2302 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-footprint-48.png =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-48.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-48.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-footprint-48.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint-48.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint-48.svg (revision 8969) @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-pcb-footprint.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-footprint.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-footprint.svg (revision 8969) @@ -0,0 +1,680 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB footprint + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-layout-16.png =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-16.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-16.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-layout-16.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-16.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-16.svg (revision 8969) @@ -0,0 +1,1333 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-layout-22.png =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-22.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-22.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-layout-22.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-22.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-22.svg (revision 8969) @@ -0,0 +1,1423 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-layout-24.png =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-24.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-24.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/data/application-x-pcb-layout-32.png =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-32.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-32.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-layout-32.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-32.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-32.svg (revision 8969) @@ -0,0 +1,1362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-layout-48.png =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-48.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-48.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-layout-48.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-layout-48.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout-48.svg (revision 8969) @@ -0,0 +1,1341 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-pcb-layout.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-layout.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-layout.svg (revision 8969) @@ -0,0 +1,1346 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB layout + + + + + + + Peter Clifton, Tomaz Solc, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-netlist-16.png =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-16.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-16.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-netlist-16.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-16.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-16.svg (revision 8969) @@ -0,0 +1,530 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-netlist-22.png =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-22.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-22.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-netlist-22.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-22.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-22.svg (revision 8969) @@ -0,0 +1,567 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-netlist-24.png =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-24.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-24.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/data/application-x-pcb-netlist-32.png =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-32.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-32.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-netlist-32.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-32.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-32.svg (revision 8969) @@ -0,0 +1,1310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/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.3/data/application-x-pcb-netlist-48.png =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-48.png (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-48.png (revision 8969) Property changes on: tags/1.2.3/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.3/data/application-x-pcb-netlist-48.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist-48.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist-48.svg (revision 8969) @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/application-x-pcb-netlist.svg =================================================================== --- tags/1.2.3/data/application-x-pcb-netlist.svg (nonexistent) +++ tags/1.2.3/data/application-x-pcb-netlist.svg (revision 8969) @@ -0,0 +1,459 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + PCB netlist + + + + + + + Peter Clifton, Jakub Steiner + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/icon-theme-installer =================================================================== --- tags/1.2.3/data/icon-theme-installer (nonexistent) +++ tags/1.2.3/data/icon-theme-installer (revision 8969) @@ -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.3/data/icon-theme-installer ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/data/pcb-48.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/pcb-48.png =================================================================== --- tags/1.2.3/data/pcb-48.png (nonexistent) +++ tags/1.2.3/data/pcb-48.png (revision 8969) Property changes on: tags/1.2.3/data/pcb-48.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/data/pcb.desktop =================================================================== --- tags/1.2.3/data/pcb.desktop (nonexistent) +++ tags/1.2.3/data/pcb.desktop (revision 8969) @@ -0,0 +1,10 @@ +[Desktop Entry] +Version=1.0 +Name=PCB Designer +GenericName=PCB Design +Comment=Create and edit printed circuit board designs +Type=Application +Exec=pcb %f +Icon=pcb +MimeType=application/x-pcb-layout;application/x-pcb-footprint; +Categories=Engineering;Electronics; Index: tags/1.2.3/data/pcb.svg =================================================================== --- tags/1.2.3/data/pcb.svg (nonexistent) +++ tags/1.2.3/data/pcb.svg (revision 8969) @@ -0,0 +1,1070 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + Lapo Calamandrei + + + + Text editor + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/data/pcb.xml =================================================================== --- tags/1.2.3/data/pcb.xml (nonexistent) +++ tags/1.2.3/data/pcb.xml (revision 8969) @@ -0,0 +1,40 @@ + + + + + PCB layout + + + + + + + + PCB footprint + + + + + + + + PCB netlist + + + + + Gerber file + + + + + + + + Excellon drill file + + + + + + Index: tags/1.2.3/data/pcb_icon.ico =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/data/pcb_icon.ico =================================================================== --- tags/1.2.3/data/pcb_icon.ico (nonexistent) +++ tags/1.2.3/data/pcb_icon.ico (revision 8969) Property changes on: tags/1.2.3/data/pcb_icon.ico ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/data/regen_files =================================================================== --- tags/1.2.3/data/regen_files (nonexistent) +++ tags/1.2.3/data/regen_files (revision 8969) @@ -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.3/data/regen_files ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/data/x-excellon.desktop =================================================================== --- tags/1.2.3/data/x-excellon.desktop (nonexistent) +++ tags/1.2.3/data/x-excellon.desktop (revision 8969) @@ -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.3/data/x-gerber.desktop =================================================================== --- tags/1.2.3/data/x-gerber.desktop (nonexistent) +++ tags/1.2.3/data/x-gerber.desktop (revision 8969) @@ -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.3/data/x-pcb-footprint.desktop =================================================================== --- tags/1.2.3/data/x-pcb-footprint.desktop (nonexistent) +++ tags/1.2.3/data/x-pcb-footprint.desktop (revision 8969) @@ -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.3/data/x-pcb-layout.desktop =================================================================== --- tags/1.2.3/data/x-pcb-layout.desktop (nonexistent) +++ tags/1.2.3/data/x-pcb-layout.desktop (revision 8969) @@ -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.3/data/x-pcb-netlist.desktop =================================================================== --- tags/1.2.3/data/x-pcb-netlist.desktop (nonexistent) +++ tags/1.2.3/data/x-pcb-netlist.desktop (revision 8969) @@ -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.3/doc/Autostyle.html =================================================================== --- tags/1.2.3/doc/Autostyle.html (nonexistent) +++ tags/1.2.3/doc/Autostyle.html (revision 8969) @@ -0,0 +1,15 @@ + + + + + + + +
Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
+ Index: tags/1.2.3/doc/Autostyle.sh =================================================================== --- tags/1.2.3/doc/Autostyle.sh (nonexistent) +++ tags/1.2.3/doc/Autostyle.sh (revision 8969) @@ -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.3/doc/Autostyle.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/Makefile =================================================================== --- tags/1.2.3/doc/Makefile (nonexistent) +++ tags/1.2.3/doc/Makefile (revision 8969) @@ -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.3/doc/README =================================================================== --- tags/1.2.3/doc/README (nonexistent) +++ tags/1.2.3/doc/README (revision 8969) @@ -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.3/doc/TODO =================================================================== --- tags/1.2.3/doc/TODO (nonexistent) +++ tags/1.2.3/doc/TODO (revision 8969) @@ -0,0 +1,215 @@ + + +- 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 + +- replace settings with lihata (conf_*) + - TEST: + - vendor drill mapping (all functionality, including regex based refdes ignore) + - route style in gtk and lesstif, save, load, 0, 1 or a lot of styles + - route style vs. autorouter + +- 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 + +AFTER THE NEXT RELEASE: +- BUGS: + - cycledrag doesn't work on arc endpoint + line endpoint [report:Ade] + - library window: allow long tags and long location text to split + - undo on new layer from right-click menu in gtk layerselk doesn't work + - using the q key to make a pin square works, from menu (info/key bindings): undo error [report: EvanFoss] + - replace default font with OSI lht font, load a file with embedded default font -> get both fonts in the same slot [report: miloh] +- gtk layersel feature requests: + - consider to provide a config setting for making open-group-name horizontal [report: istankovic] +- cleanup: remove mnemonic from the menu system + - check the central code and struct fields + - remove "m=" fields from the menu lihata files +- fontsel: + - replace font in slot (even in default) + - ttf import? +- cleanup: revise strftime() calls, especially in exporters: + - make a config.h format string, don't depend on %c + - make the format more ISO-like + - make sure to use this in all the exported comments but don't break file formats +- fp_board: extend the API so that the element can be presented without saving to a file +- layer rewrite: central menu buttons + - lesstif needs to remember the widgets via lb->w in menu.c + - rewrite the central code for callbacks? +- BUG: when DRC sizes are saved in user conf, they are overridden from the default.pcb [report: Alain] + Reason: pcb_board_t Bloat, Shrink, minWid, minSlk, minDrill, minRing -> remove them, use values from the config system instead +- 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] +- 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 +- extend the DRC window to be a generic location list + - buttons to select one or all items or all items including locked + - multiple DRC windows + - 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 +- hid_gtk? bug: moving with cursor keys snapping to a via - can't leave with cursor keys! +- io_pcb: new, optional "layer tag" field in mainline's file format +- inconsistencies in UI/terminology: + - allow clearance to be set to 0 in the route style [report: miloh] + - similar thing on hole size [report: miloh] + - report dialog should use the same terminology for clearances as elements and route style dialog [report: miloh] +- GTK layers [report: Ade]: + - move the layer+selected color change from the preferences menu to the layer popup (but this should probably live in gui-config.h) +- 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 +- BUG: arcbug1.lht: draw a polygon over the rightmost ^ arc and it will calculate a self-intersecting clearance [report:Evan] +- draw code: pin numbers/names are drawn under the silk: pins/pads are drawn in one go, both copper and the numbering, and the copper needs to go under the silk so the number ends up there too [report:Evan] +- lihata board: + - move generates much more diff than reasonable: does it renumber IDs? +- save buffer element to file - preferred format is hardwired and file name guess is crude (function Save() in gtkhid-main.c) +- pcb_act_Attributes -> this could be handled by the property editor maybe? but what about layout attributes and the lesstif hid? +- unravel the undo code + - grid size change should be undoable? [report:Evan] + - maybe other conf settings too? +- search for move.dst_layer - don't compare pointer to -1! +- dir rename trunk/pcblib/tru-hole should handle make correctly and not walk on existing web services or user installs +- grid status line label doesn't update when using setvalue(grid,delta) add another hook to update this value [miloh] +- Erich's select undo bug: place an element, select, save & load, unselect, undo 2 times: bad serial +- 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 +- mark bug - ortho shouldn't use it, it should use last point (crosshair.X2); make sure nothing else abuses it [James] +- improve locking: + - consider a move-only lock + - when thermal and some other operations are applied on a locked element, indicate it +- 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 + - debug why 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 +- action bug: gui_act.c shouldn't reference Crosshair.X directly; check d-fix.patch about how to fix it +- next_gui: keep them open, hide +- look for #warnings +- libstroke: zoom +- cleanup/rewrite resources: + - load/swap menus (TODO#1) + - gpmi: + - hid: hid_destroy (pair of hid_create) + - cleanup on unload: remove menus +- check gpmi when pcb-rnd is fully linstalled - broken symlinks? +- multi-key: display state on the gui +- TODO#3: works only on US keyboard +- gtk hid: display element numbers; flip board with tab: numbers get mirrored [report:Evan] +- 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 + +LATER RELEASES: +- parametric footprint gtk attribute box for editing: also mention the default value in the tooltip [report: agaran] +- silent failure on parser error in io_pcb: e.g. missing or non-integer fields of Via[] [report: Erich] +- core lib splitup: + - gsch2pcb: generalize plugin/buildin loading for external tools, check if gsch2pcb can work from plugins +- lihata board/fp format: + - pads should be polygons (0 long line can't be rotated!) + - footprint orientation with a vector (just a second point) +- layer groups from config (e.g. CLI) is ignored +- res: + - 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 +- main.c: + - SIGPIPE - detect it (needed for popen) + +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 + +Low prio: +- 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] +- 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 +- 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 +- examine current handling of long options [miloh] +- --dump-actions shows gpmi paths ( is this related? it looks unexpected to me) +- unify gui invocation options: why do pcb --help gtk & pcb --help lesstif show different input methods [report:miloh] Index: tags/1.2.3/doc/UNIX.txt =================================================================== --- tags/1.2.3/doc/UNIX.txt (nonexistent) +++ tags/1.2.3/doc/UNIX.txt (revision 8969) @@ -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.3/doc/conf/groups.html =================================================================== --- tags/1.2.3/doc/conf/groups.html (nonexistent) +++ tags/1.2.3/doc/conf/groups.html (revision 8969) @@ -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.3/doc/conf/index.html =================================================================== --- tags/1.2.3/doc/conf/index.html (nonexistent) +++ tags/1.2.3/doc/conf/index.html (revision 8969) @@ -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.3/doc/conf/index_prog.html =================================================================== --- tags/1.2.3/doc/conf/index_prog.html (nonexistent) +++ tags/1.2.3/doc/conf/index_prog.html (revision 8969) @@ -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.3/doc/conf/index_user.html =================================================================== --- tags/1.2.3/doc/conf/index_user.html (nonexistent) +++ tags/1.2.3/doc/conf/index_user.html (revision 8969) @@ -0,0 +1,99 @@ + + + + pcb-rnd - config for users + + + +

The new config system in pcb-rnd

+

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 .pcb +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.3/doc/conf/lists.html =================================================================== --- tags/1.2.3/doc/conf/lists.html (nonexistent) +++ tags/1.2.3/doc/conf/lists.html (revision 8969) @@ -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.3/doc/conf/merging.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/conf/merging.png =================================================================== --- tags/1.2.3/doc/conf/merging.png (nonexistent) +++ tags/1.2.3/doc/conf/merging.png (revision 8969) Property changes on: tags/1.2.3/doc/conf/merging.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/conf/noextend.html =================================================================== --- tags/1.2.3/doc/conf/noextend.html (nonexistent) +++ tags/1.2.3/doc/conf/noextend.html (revision 8969) @@ -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.3/doc/conf/plugin_chk.html =================================================================== --- tags/1.2.3/doc/conf/plugin_chk.html (nonexistent) +++ tags/1.2.3/doc/conf/plugin_chk.html (revision 8969) @@ -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.3/doc/conf/prio.html =================================================================== --- tags/1.2.3/doc/conf/prio.html (nonexistent) +++ tags/1.2.3/doc/conf/prio.html (revision 8969) @@ -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.3/doc/conf/scalars.html =================================================================== --- tags/1.2.3/doc/conf/scalars.html (nonexistent) +++ tags/1.2.3/doc/conf/scalars.html (revision 8969) @@ -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.3/doc/conf/sources.html =================================================================== --- tags/1.2.3/doc/conf/sources.html (nonexistent) +++ tags/1.2.3/doc/conf/sources.html (revision 8969) @@ -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.3/doc/conf/src/Makefile =================================================================== --- tags/1.2.3/doc/conf/src/Makefile (nonexistent) +++ tags/1.2.3/doc/conf/src/Makefile (revision 8969) @@ -0,0 +1,2 @@ +../merging.png: merging.dot + dot -Tpng merging.dot > ../merging.png \ No newline at end of file Index: tags/1.2.3/doc/conf/src/merging.dot =================================================================== --- tags/1.2.3/doc/conf/src/merging.dot (nonexistent) +++ tags/1.2.3/doc/conf/src/merging.dot (revision 8969) @@ -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.3/doc/conf/syntax.html =================================================================== --- tags/1.2.3/doc/conf/syntax.html (nonexistent) +++ tags/1.2.3/doc/conf/syntax.html (revision 8969) @@ -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.3/doc/conf/tree/CFN_BOOLEAN.html =================================================================== --- tags/1.2.3/doc/conf/tree/CFN_BOOLEAN.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/CFN_BOOLEAN.html (revision 8969) @@ -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.3/doc/conf/tree/CFN_COLOR.html =================================================================== --- tags/1.2.3/doc/conf/tree/CFN_COLOR.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/CFN_COLOR.html (revision 8969) @@ -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.3/doc/conf/tree/CFN_COORD.html =================================================================== --- tags/1.2.3/doc/conf/tree/CFN_COORD.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/CFN_COORD.html (revision 8969) @@ -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.3/doc/conf/tree/CFN_INCREMENTS.html =================================================================== --- tags/1.2.3/doc/conf/tree/CFN_INCREMENTS.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/CFN_INCREMENTS.html (revision 8969) @@ -0,0 +1,8 @@ + + +

pcb-rnd conf tree

+

type: increments

+A collection of coordinates representing an increment configuration. +

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

pcb-rnd conf tree

+

type: string

+Text value. +

+Example values: +

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

pcb-rnd conf tree

+

type: unit

+Name of a unit. +

+Example values: mm, cm, m, mil + + Index: tags/1.2.3/doc/conf/tree/appearance.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance.html (revision 8969) @@ -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.3/doc/conf/tree/appearance_color.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance_color.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance_color.html (revision 8969) @@ -0,0 +1,31 @@ + +

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 +
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.3/doc/conf/tree/appearance_loglevels.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance_loglevels.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance_loglevels.html (revision 8969) @@ -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.3/doc/conf/tree/appearance_messages.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance_messages.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance_messages.html (revision 8969) @@ -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.3/doc/conf/tree/appearance_misc.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance_misc.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance_misc.html (revision 8969) @@ -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.3/doc/conf/tree/appearance_pinout.html =================================================================== --- tags/1.2.3/doc/conf/tree/appearance_pinout.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/appearance_pinout.html (revision 8969) @@ -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.3/doc/conf/tree/design.html =================================================================== --- tags/1.2.3/doc/conf/tree/design.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/design.html (revision 8969) @@ -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.3/doc/conf/tree/editor.html =================================================================== --- tags/1.2.3/doc/conf/tree/editor.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/editor.html (revision 8969) @@ -0,0 +1,51 @@ + +

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. +
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. +
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. +
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.3/doc/conf/tree/editor_selection.html =================================================================== --- tags/1.2.3/doc/conf/tree/editor_selection.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/editor_selection.html (revision 8969) @@ -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.3/doc/conf/tree/editor_view.html =================================================================== --- tags/1.2.3/doc/conf/tree/editor_view.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/editor_view.html (revision 8969) @@ -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.3/doc/conf/tree/rc.html =================================================================== --- tags/1.2.3/doc/conf/tree/rc.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/rc.html (revision 8969) @@ -0,0 +1,27 @@ + +

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 +
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. +
backup_name string 0 file name template for periodic backup anonymous .pcb files; optional fields: %P --> pid +
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. +
have_regex boolean 0 whether we have regex compiled in +
Index: tags/1.2.3/doc/conf/tree/rc_path.html =================================================================== --- tags/1.2.3/doc/conf/tree/rc_path.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/rc_path.html (revision 8969) @@ -0,0 +1,12 @@ + +

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]) +
Index: tags/1.2.3/doc/conf/tree/temp.html =================================================================== --- tags/1.2.3/doc/conf/tree/temp.html (nonexistent) +++ tags/1.2.3/doc/conf/tree/temp.html (revision 8969) @@ -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.3/doc/contrib.html =================================================================== --- tags/1.2.3/doc/contrib.html (nonexistent) +++ tags/1.2.3/doc/contrib.html (revision 8969) @@ -0,0 +1,69 @@ + + + + + pcb-rnd - contribution + + + + + + + + + +
Main + News + Doc + 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.3/doc/datasheet.html =================================================================== --- tags/1.2.3/doc/datasheet.html (nonexistent) +++ tags/1.2.3/doc/datasheet.html (revision 8969) @@ -0,0 +1,79 @@ + + + + pcb-rnd - datasheet + + + + + + + + + + +
Main + News + Doc + 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.3/doc/developer/blog_queue.txt =================================================================== --- tags/1.2.3/doc/developer/blog_queue.txt (nonexistent) +++ tags/1.2.3/doc/developer/blog_queue.txt (revision 8969) @@ -0,0 +1,17 @@ +Ready to blog: +- fp_board +- bitmap -> silkscreen insertion dialogue - bitmap() (another chance to spam edakrill) +- Ade's route stuff, current state, with video + +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.3/doc/developer/bridges/Makefile =================================================================== --- tags/1.2.3/doc/developer/bridges/Makefile (nonexistent) +++ tags/1.2.3/doc/developer/bridges/Makefile (revision 8969) @@ -0,0 +1,6 @@ +bridges.svg: bridges.dot + dot -Tsvg bridges.dot > bridges.svg + +bridges.png: bridges.dot + dot -Tpng bridges.dot > bridges.png + Index: tags/1.2.3/doc/developer/bridges/bridges.dot =================================================================== --- tags/1.2.3/doc/developer/bridges/bridges.dot (nonexistent) +++ tags/1.2.3/doc/developer/bridges/bridges.dot (revision 8969) @@ -0,0 +1,113 @@ +digraph gr { + rankdir=LR + nodesep=0.6 + + pcbrnd [label="pcb-rnd" style=filled fillcolor=cyan shape=box height=12 width=2] + kicad [label="KiCad\npcbnew" shape=box] + eeschema [label="KiCad\neeschema" shape=box] + pcb [label="gEDA/PCB" shape=box] + freerouting [label="freerouting.net\njava application" shape=box] + mucs [label="mucs pcb with autorouter" shape=box] + gEDA [label="gEDA/gaf\n(gschem, gnetlist)" shape=box] + lepton [label="lepton-eda\n(gschem, gnetlist)" shape=box] + ltspice [label="LTSpice" shape=box] + tinycad [label="TinyCAD" shape=box] + web [label="JavaScript based\nweb application\n(work in progress)" shape=box color="#aaaaaa" fontcolor="#aaaaaa"] + fidocadj [label="FidoCadj\nartistic PCBs\n(experimental support)" shape=box] + + subgraph cluster_HID { + label = "HID - user interface" + style=filled + color="#dddddd" + + batch [label="hid_batch" shape=diamond] + gtk [label="hid_gtk" shape=diamond] + lesstif [label="hid_lesstif" shape=diamond] + remote [label="hid_remote" shape=diamond] + } + + subgraph cluster_import { + label = "import only" + style=filled + color="#dddddd" + + lepton + mucs + edif + ltspice + netlist + tinycad + eeschema + } + + subgraph cluster_export { + label = "export only" + style=filled + color="#dddddd" + + breadboard + BoM + XY + gerber + ipcd356 + lpr + nelma + png + ps + stat + svg + } + + subgraph cluster_ie { + label = "import and export" + style=filled + color="#dddddd" + + gEDA + kicad + pcb + freerouting + fidocadj + } + + pcbrnd -> kicad [label="board: legacy format"] + pcbrnd -> kicad [label="board: s-expression" dir=both] + pcbrnd -> kicad [label="footprint: s-expression" dir=both] + pcbrnd -> fidocadj [label="board" dir=both] + + eeschema -> pcbrnd [label="netlist"] + + pcbrnd -> pcb [label="board: .pcb" dir=both] + pcbrnd -> pcb [label="footprint: .fp" dir=both] + + pcbrnd -> freerouting [label=".dsn" dir=both] + mucs -> pcbrnd [label="import"] + + pcbrnd -> breadboard [label=".png"] + pcbrnd -> BoM [label="text"] + pcbrnd -> XY [label=".xy\nfor pick and place"] + pcbrnd -> gerber [label=".gbr, .cnc"] + pcbrnd -> ipcd356 + pcbrnd -> lpr [label="print"] + pcbrnd -> nelma + pcbrnd -> png [label="bitmap"] + pcbrnd -> ps [label=".ps, .eps"] + pcbrnd -> stat [label="statsitics .lht"] + pcbrnd -> svg [label=".svg"] + + edif -> pcbrnd + ltspice -> pcbrnd [label="schematics"] + netlist -> pcbrnd [label="pcb .net"] + lepton -> pcbrnd [label="schematics"] + gEDA -> pcbrnd [label="schematics\nback annotation" dir=both] + tinycad -> pcbrnd [label="schematics"] + + pcbrnd -> batch [dir=both] + pcbrnd -> gtk [dir=both] + pcbrnd -> lesstif [dir=both] + pcbrnd -> remote [dir=both] + + remote -> web [dir=both] + + ps -> pcbrnd [weight=1000 style=invis] +} Index: tags/1.2.3/doc/developer/bridges/bridges.svg =================================================================== --- tags/1.2.3/doc/developer/bridges/bridges.svg (nonexistent) +++ tags/1.2.3/doc/developer/bridges/bridges.svg (revision 8969) @@ -0,0 +1,376 @@ + + + + + + +gr + +cluster_HID + +HID - user interface + +cluster_import + +import only + +cluster_export + +export only + +cluster_ie + +import and export + + +pcbrnd + +pcb-rnd + + +kicad + +KiCad +pcbnew + + +pcbrnd->kicad + + +board: legacy format + + +pcbrnd->kicad + + + +board: s-expression + + +pcbrnd->kicad + + + +footprint: s-expression + + +pcb + +gEDA/PCB + + +pcbrnd->pcb + + + +board: .pcb + + +pcbrnd->pcb + + + +footprint: .fp + + +freerouting + +freerouting.net +java application + + +pcbrnd->freerouting + + + +.dsn + + +fidocadj + +FidoCadj +artistic PCBs +(experimental support) + + +pcbrnd->fidocadj + + + +board + + +batch + +hid_batch + + +pcbrnd->batch + + + + + +gtk + +hid_gtk + + +pcbrnd->gtk + + + + + +lesstif + +hid_lesstif + + +pcbrnd->lesstif + + + + + +remote + +hid_remote + + +pcbrnd->remote + + + + + +breadboard + +breadboard + + +pcbrnd->breadboard + + +.png + + +BoM + +BoM + + +pcbrnd->BoM + + +text + + +XY + +XY + + +pcbrnd->XY + + +.xy +for pick and place + + +gerber + +gerber + + +pcbrnd->gerber + + +.gbr, .cnc + + +ipcd356 + +ipcd356 + + +pcbrnd->ipcd356 + + + + +lpr + +lpr + + +pcbrnd->lpr + + +print + + +nelma + +nelma + + +pcbrnd->nelma + + + + +png + +png + + +pcbrnd->png + + +bitmap + + +ps + +ps + + +pcbrnd->ps + + +.ps, .eps + + +stat + +stat + + +pcbrnd->stat + + +statsitics .lht + + +svg + +svg + + +pcbrnd->svg + + +.svg + + +eeschema + +KiCad +eeschema + + +eeschema->pcbrnd + + +netlist + + +mucs + +mucs pcb with autorouter + + +mucs->pcbrnd + + +import + + +gEDA + +gEDA/gaf +(gschem, gnetlist) + + +gEDA->pcbrnd + + + +schematics +back annotation + + +lepton + +lepton-eda +(gschem, gnetlist) + + +lepton->pcbrnd + + +schematics + + +ltspice + +LTSpice + + +ltspice->pcbrnd + + +schematics + + +tinycad + +TinyCAD + + +tinycad->pcbrnd + + +schematics + + +web + +JavaScript based +web application +(work in progress) + + +remote->web + + + + + +edif + +edif + + +edif->pcbrnd + + + + +netlist + +netlist + + +netlist->pcbrnd + + +pcb .net + + + + Index: tags/1.2.3/doc/developer/bugreport.html =================================================================== --- tags/1.2.3/doc/developer/bugreport.html (nonexistent) +++ tags/1.2.3/doc/developer/bugreport.html (revision 8969) @@ -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.3/doc/developer/c89.html =================================================================== --- tags/1.2.3/doc/developer/c89.html (nonexistent) +++ tags/1.2.3/doc/developer/c89.html (revision 8969) @@ -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.3/doc/developer/data.html =================================================================== --- tags/1.2.3/doc/developer/data.html (nonexistent) +++ tags/1.2.3/doc/developer/data.html (revision 8969) @@ -0,0 +1,103 @@ + + + +

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 a "subcircuit" related +to an existing board: +
    +
  • per-layer objects (e.g. lines, arcs, polygons) +
  • global objects (e.g. elements, vias) +
  • temporary logical connections (rat lines) +
+

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

buffers

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

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

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

    +
  • solder mask - no layer struct, calculated on-the-fly from pad data +
  • paste - 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. The other 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. + +

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.3/doc/developer/data1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/data1.png =================================================================== --- tags/1.2.3/doc/developer/data1.png (nonexistent) +++ tags/1.2.3/doc/developer/data1.png (revision 8969) Property changes on: tags/1.2.3/doc/developer/data1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/developer/ddrc/examples1.txt =================================================================== --- tags/1.2.3/doc/developer/ddrc/examples1.txt (nonexistent) +++ tags/1.2.3/doc/developer/ddrc/examples1.txt (revision 8969) @@ -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.3/doc/developer/ddrc/proposal1.txt =================================================================== --- tags/1.2.3/doc/developer/ddrc/proposal1.txt (nonexistent) +++ tags/1.2.3/doc/developer/ddrc/proposal1.txt (revision 8969) @@ -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.3/doc/developer/ddrc/requirements.txt =================================================================== --- tags/1.2.3/doc/developer/ddrc/requirements.txt (nonexistent) +++ tags/1.2.3/doc/developer/ddrc/requirements.txt (revision 8969) @@ -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.3/doc/developer/distros.txt =================================================================== --- tags/1.2.3/doc/developer/distros.txt (nonexistent) +++ tags/1.2.3/doc/developer/distros.txt (revision 8969) @@ -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.3/doc/developer/hid_gtk3/Makefile =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/Makefile (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/Makefile (revision 8969) @@ -0,0 +1,3 @@ +%.html: %.adoc + #asciidoctor --safe-mode=secure $^ + asciidoctor --safe-mode=safe $^ Index: tags/1.2.3/doc/developer/hid_gtk3/adoc_common_attributes.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/adoc_common_attributes.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/adoc_common_attributes.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/default.css =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/default.css (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/default.css (revision 8969) @@ -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.3/doc/developer/hid_gtk3/gtk_drc_dialog.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_drc_dialog.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_drc_dialog.adoc (revision 8969) @@ -0,0 +1,5 @@ +:author: Alain +include::adoc_common_attributes.adoc[] + += DRC results GUI + Index: tags/1.2.3/doc/developer/hid_gtk3/gtk_drc_dialog.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_drc_dialog.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_drc_dialog.html (revision 8969) @@ -0,0 +1,29 @@ + + + + + + + + +DRC results GUI + + + + + +
+ +
+ + + \ No newline at end of file Index: tags/1.2.3/doc/developer/hid_gtk3/gtk_hid_architecture.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_hid_architecture.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_hid_architecture.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/gtk_hid_architecture.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_hid_architecture.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_hid_architecture.html (revision 8969) @@ -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.3/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_preferences_dialog.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/gtk_preferences_dialog.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/gtk_preferences_dialog.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/gtk_preferences_dialog.html (revision 8969) @@ -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.3/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.3/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/img_route_style/gtk2-edit_route_styles_001.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/img_route_style/gtk2-pcb-rnd_001.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/hid_gtk3/includes_directives.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/includes_directives.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/includes_directives.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/includes_directives.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/includes_directives.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/includes_directives.html (revision 8969) @@ -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.3/doc/developer/hid_gtk3/index.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/index.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/index.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/index.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/index.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/index.html (revision 8969) @@ -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.3/doc/developer/hid_gtk3/layer_selection.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/layer_selection.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/layer_selection.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/layer_selection.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/layer_selection.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/layer_selection.html (revision 8969) @@ -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.3/doc/developer/hid_gtk3/route_style.adoc =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/route_style.adoc (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/route_style.adoc (revision 8969) @@ -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.3/doc/developer/hid_gtk3/route_style.html =================================================================== --- tags/1.2.3/doc/developer/hid_gtk3/route_style.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_gtk3/route_style.html (revision 8969) @@ -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.3/doc/developer/hid_remote/Makefile =================================================================== --- tags/1.2.3/doc/developer/hid_remote/Makefile (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/Makefile (revision 8969) @@ -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.3/doc/developer/hid_remote/fixlab.sh =================================================================== --- tags/1.2.3/doc/developer/hid_remote/fixlab.sh (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/fixlab.sh (revision 8969) @@ -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.3/doc/developer/hid_remote/fixlab.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/developer/hid_remote/proto_high.html =================================================================== --- tags/1.2.3/doc/developer/hid_remote/proto_high.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/proto_high.html (revision 8969) @@ -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.3/doc/developer/hid_remote/proto_low.html =================================================================== --- tags/1.2.3/doc/developer/hid_remote/proto_low.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/proto_low.html (revision 8969) @@ -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.3/doc/developer/hid_remote/proto_parse.dot =================================================================== --- tags/1.2.3/doc/developer/hid_remote/proto_parse.dot (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/proto_parse.dot (revision 8969) @@ -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.3/doc/developer/hid_remote/proto_parse.html =================================================================== --- tags/1.2.3/doc/developer/hid_remote/proto_parse.html (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/proto_parse.html (revision 8969) @@ -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.3/doc/developer/hid_remote/proto_parse.svg =================================================================== --- tags/1.2.3/doc/developer/hid_remote/proto_parse.svg (nonexistent) +++ tags/1.2.3/doc/developer/hid_remote/proto_parse.svg (revision 8969) @@ -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.3/doc/developer/import.html =================================================================== --- tags/1.2.3/doc/developer/import.html (nonexistent) +++ tags/1.2.3/doc/developer/import.html (revision 8969) @@ -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.3/doc/developer/indent.html =================================================================== --- tags/1.2.3/doc/developer/indent.html (nonexistent) +++ tags/1.2.3/doc/developer/indent.html (revision 8969) @@ -0,0 +1,15 @@ + + +

pcb-rnd - indentation

+ +As of r1022 all old code is converted using indent(1) with the following +command line: + +
+indent --line-length128 -brs -br -nce --tab-size2 -ut -npsl  -npcs -hnl $*
+
+

+Contributors are kindly asked to follow this style or run the above commandline +on their code before sending a patch or committing to svn. + + Index: tags/1.2.3/doc/developer/io_lihata_ver.html =================================================================== --- tags/1.2.3/doc/developer/io_lihata_ver.html (nonexistent) +++ tags/1.2.3/doc/developer/io_lihata_ver.html (revision 8969) @@ -0,0 +1,42 @@ + + + + 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. + +

(planned: v3)

+ ( + New global object subtree: subcircuit. Global object element has been removed. + ) + + + Index: tags/1.2.3/doc/developer/mods3/README =================================================================== --- tags/1.2.3/doc/developer/mods3/README (nonexistent) +++ tags/1.2.3/doc/developer/mods3/README (revision 8969) @@ -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.3/doc/developer/mods3/after.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/after.png =================================================================== --- tags/1.2.3/doc/developer/mods3/after.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/after.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/before.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/before.png =================================================================== --- tags/1.2.3/doc/developer/mods3/before.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/before.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/deps.svg =================================================================== --- tags/1.2.3/doc/developer/mods3/deps.svg (nonexistent) +++ tags/1.2.3/doc/developer/mods3/deps.svg (revision 8969) @@ -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.3/doc/developer/mods3/export.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/export.png =================================================================== --- tags/1.2.3/doc/developer/mods3/export.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/export.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/feature.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/feature.png =================================================================== --- tags/1.2.3/doc/developer/mods3/feature.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/feature.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/fp.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/fp.png =================================================================== --- tags/1.2.3/doc/developer/mods3/fp.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/fp.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/gen.sh =================================================================== --- tags/1.2.3/doc/developer/mods3/gen.sh (nonexistent) +++ tags/1.2.3/doc/developer/mods3/gen.sh (revision 8969) @@ -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.3/doc/developer/mods3/gen.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/developer/mods3/hid.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/hid.png =================================================================== --- tags/1.2.3/doc/developer/mods3/hid.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/hid.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/import.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/import.png =================================================================== --- tags/1.2.3/doc/developer/mods3/import.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/import.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/index.html =================================================================== --- tags/1.2.3/doc/developer/mods3/index.html (nonexistent) +++ tags/1.2.3/doc/developer/mods3/index.html (revision 8969) @@ -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.3/doc/developer/mods3/io.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/io.png =================================================================== --- tags/1.2.3/doc/developer/mods3/io.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/io.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/lib.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/lib.png =================================================================== --- tags/1.2.3/doc/developer/mods3/lib.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/lib.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/mods.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/developer/mods3/mods.png =================================================================== --- tags/1.2.3/doc/developer/mods3/mods.png (nonexistent) +++ tags/1.2.3/doc/developer/mods3/mods.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/developer/mods3/post.html =================================================================== --- tags/1.2.3/doc/developer/mods3/post.html (nonexistent) +++ tags/1.2.3/doc/developer/mods3/post.html (revision 8969) @@ -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.3/doc/developer/mods3/pre.html =================================================================== --- tags/1.2.3/doc/developer/mods3/pre.html (nonexistent) +++ tags/1.2.3/doc/developer/mods3/pre.html (revision 8969) @@ -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.3/doc/developer/obj_func_naming.txt =================================================================== --- tags/1.2.3/doc/developer/obj_func_naming.txt (nonexistent) +++ tags/1.2.3/doc/developer/obj_func_naming.txt (revision 8969) @@ -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.3/doc/developer/packaging.txt =================================================================== --- tags/1.2.3/doc/developer/packaging.txt (nonexistent) +++ tags/1.2.3/doc/developer/packaging.txt (revision 8969) @@ -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.3/doc/developer/plugin_core_simple.html =================================================================== --- tags/1.2.3/doc/developer/plugin_core_simple.html (nonexistent) +++ tags/1.2.3/doc/developer/plugin_core_simple.html (revision 8969) @@ -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.3/doc/developer/plugin_naming.html =================================================================== --- tags/1.2.3/doc/developer/plugin_naming.html (nonexistent) +++ tags/1.2.3/doc/developer/plugin_naming.html (revision 8969) @@ -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.3/doc/developer/releasing.txt =================================================================== --- tags/1.2.3/doc/developer/releasing.txt (nonexistent) +++ tags/1.2.3/doc/developer/releasing.txt (revision 8969) @@ -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.3/doc/developer/renames =================================================================== --- tags/1.2.3/doc/developer/renames (nonexistent) +++ tags/1.2.3/doc/developer/renames (revision 8969) @@ -0,0 +1,1516 @@ +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 Index: tags/1.2.3/doc/developer/src/Makefile =================================================================== --- tags/1.2.3/doc/developer/src/Makefile (nonexistent) +++ tags/1.2.3/doc/developer/src/Makefile (revision 8969) @@ -0,0 +1,2 @@ +../data1.png: data1.dot + dot -Tpng $^ > $@ Index: tags/1.2.3/doc/developer/src/data1.dot =================================================================== --- tags/1.2.3/doc/developer/src/data1.dot (nonexistent) +++ tags/1.2.3/doc/developer/src/data1.dot (revision 8969) @@ -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"] + 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.3/doc/devlog/20150731a_menu.html =================================================================== --- tags/1.2.3/doc/devlog/20150731a_menu.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150731a_menu.html (revision 8969) @@ -0,0 +1,59 @@ + + +

pcb-rnd devlog

+

Dynamic menus

+

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.3/doc/devlog/20150731b_gtk.html =================================================================== --- tags/1.2.3/doc/devlog/20150731b_gtk.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150731b_gtk.html (revision 8969) @@ -0,0 +1,36 @@ + + +

pcb-rnd devlog

+

dynamic gtk menus

+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.3/doc/devlog/20150801a_events.html =================================================================== --- tags/1.2.3/doc/devlog/20150801a_events.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150801a_events.html (revision 8969) @@ -0,0 +1,22 @@ + + +

pcb-rnd devlog

+

events

+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.3/doc/devlog/20150803a_scriptig.html =================================================================== --- tags/1.2.3/doc/devlog/20150803a_scriptig.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150803a_scriptig.html (revision 8969) @@ -0,0 +1,36 @@ + + +

pcb-rnd devlog

+

scripting

+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.3/doc/devlog/20150816a_scriptig.html =================================================================== --- tags/1.2.3/doc/devlog/20150816a_scriptig.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150816a_scriptig.html (revision 8969) @@ -0,0 +1,28 @@ + + +

pcb-rnd devlog

+

scripting, 2

+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.3/doc/devlog/20150820a_dimensions.html =================================================================== --- tags/1.2.3/doc/devlog/20150820a_dimensions.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150820a_dimensions.html (revision 8969) @@ -0,0 +1,24 @@ + + +

pcb-rnd devlog

+

fp2anim dimensions

+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.3/doc/devlog/20150820b_qf.html =================================================================== --- tags/1.2.3/doc/devlog/20150820b_qf.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150820b_qf.html (revision 8969) @@ -0,0 +1,27 @@ + + +

pcb-rnd devlog

+

qf()

+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.3/doc/devlog/20150821a_parametric_requirements.html =================================================================== --- tags/1.2.3/doc/devlog/20150821a_parametric_requirements.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150821a_parametric_requirements.html (revision 8969) @@ -0,0 +1,32 @@ + + +

pcb-rnd devlog

+

requirements for parametric footprint generation

+ +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.3/doc/devlog/20150830a_fork_faq.html =================================================================== --- tags/1.2.3/doc/devlog/20150830a_fork_faq.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150830a_fork_faq.html (revision 8969) @@ -0,0 +1,246 @@ + + +

pcb-rnd devlog

+ +

Fork FAQ

+ +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.3/doc/devlog/20150830b_back_ann.html =================================================================== --- tags/1.2.3/doc/devlog/20150830b_back_ann.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150830b_back_ann.html (revision 8969) @@ -0,0 +1,304 @@ + + +

pcb-rnd devlog

+ +

back annotation

+ +

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.3/doc/devlog/20150901a_back_ann.html =================================================================== --- tags/1.2.3/doc/devlog/20150901a_back_ann.html (nonexistent) +++ tags/1.2.3/doc/devlog/20150901a_back_ann.html (revision 8969) @@ -0,0 +1,87 @@ + + +

pcb-rnd devlog

+ +

back annotation

+ + +

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.3/doc/devlog/20151028_glib.html =================================================================== --- tags/1.2.3/doc/devlog/20151028_glib.html (nonexistent) +++ tags/1.2.3/doc/devlog/20151028_glib.html (revision 8969) @@ -0,0 +1,65 @@ + + +

pcb-rnd devlog

+ +

why glib is a bad idea

+ +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.3/doc/devlog/20160101_cschem.html =================================================================== --- tags/1.2.3/doc/devlog/20160101_cschem.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160101_cschem.html (revision 8969) @@ -0,0 +1,68 @@ + + +

pcb-rnd devlog

+ +

cschem

+ +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 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.3/doc/devlog/20160126.html =================================================================== --- tags/1.2.3/doc/devlog/20160126.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160126.html (revision 8969) @@ -0,0 +1,59 @@ + + +

pcb-rnd devlog

+ +

Burried/blind via poll

+ +

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.3/doc/devlog/20160313_unglib.html =================================================================== --- tags/1.2.3/doc/devlog/20160313_unglib.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160313_unglib.html (revision 8969) @@ -0,0 +1,49 @@ + + +

pcb-rnd devlog

+ +

unglib: glib removal

+ +

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.3/doc/devlog/20160314_valgrind_flex.html =================================================================== --- tags/1.2.3/doc/devlog/20160314_valgrind_flex.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160314_valgrind_flex.html (revision 8969) @@ -0,0 +1,79 @@ + + +

pcb-rnd devlog

+ +

"valgrinding" flex/bison parsers

+ +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.3/doc/devlog/20160409/header =================================================================== --- tags/1.2.3/doc/devlog/20160409/header (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/header (revision 8969) @@ -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.3/doc/devlog/20160409/header.csv =================================================================== --- tags/1.2.3/doc/devlog/20160409/header.csv (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/header.csv (revision 8969) @@ -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.3/doc/devlog/20160409/legend.txt =================================================================== --- tags/1.2.3/doc/devlog/20160409/legend.txt (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/legend.txt (revision 8969) @@ -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.3/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.3/doc/devlog/20160409/pie_col_1.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_1.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_1.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/devlog/20160409/pie_col_2.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_2.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_2.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/devlog/20160409/pie_col_3.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_3.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_3.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/devlog/20160409/pie_col_4.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_4.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_4.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/devlog/20160409/pie_col_5.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_5.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_5.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/devlog/20160409/pie_col_7.png =================================================================== --- tags/1.2.3/doc/devlog/20160409/pie_col_7.png (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/pie_col_7.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/20160409/poll.csv =================================================================== --- tags/1.2.3/doc/devlog/20160409/poll.csv (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/poll.csv (revision 8969) @@ -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.3/doc/devlog/20160409/poll.html =================================================================== --- tags/1.2.3/doc/devlog/20160409/poll.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/poll.html (revision 8969) @@ -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.3/doc/devlog/20160409/poll.tsv =================================================================== --- tags/1.2.3/doc/devlog/20160409/poll.tsv (nonexistent) +++ tags/1.2.3/doc/devlog/20160409/poll.tsv (revision 8969) @@ -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.3/doc/devlog/20160409.html =================================================================== --- tags/1.2.3/doc/devlog/20160409.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160409.html (revision 8969) @@ -0,0 +1,48 @@ + + +

      pcb-rnd devlog

      + +

      Keyboard via poll

      + +

      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.3/doc/devlog/20160716_sprint.html =================================================================== --- tags/1.2.3/doc/devlog/20160716_sprint.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160716_sprint.html (revision 8969) @@ -0,0 +1,81 @@ + + +

      pcb-rnd devlog

      + +

      Testing guide for the test sprint

      + +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.3/doc/devlog/20160802.html =================================================================== --- tags/1.2.3/doc/devlog/20160802.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160802.html (revision 8969) @@ -0,0 +1,25 @@ + + +

        pcb-rnd devlog

        + +

        Languages and libs

        + +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.3/doc/devlog/20160808_model.html =================================================================== --- tags/1.2.3/doc/devlog/20160808_model.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160808_model.html (revision 8969) @@ -0,0 +1,101 @@ + + +

        pcb-rnd devlog

        + +

        How to represent the world in pcb-rnd

        + +

        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.3/doc/devlog/20160823_lhtpers.html =================================================================== --- tags/1.2.3/doc/devlog/20160823_lhtpers.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160823_lhtpers.html (revision 8969) @@ -0,0 +1,209 @@ + + +

        pcb-rnd devlog

        + +

        File format vs. VCS vs. script and manual editing

        + +

        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.3/doc/devlog/20160826_virtusers.html =================================================================== --- tags/1.2.3/doc/devlog/20160826_virtusers.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160826_virtusers.html (revision 8969) @@ -0,0 +1,65 @@ + + +

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

        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.3/doc/devlog/20160921_gl.html =================================================================== --- tags/1.2.3/doc/devlog/20160921_gl.html (nonexistent) +++ tags/1.2.3/doc/devlog/20160921_gl.html (revision 8969) @@ -0,0 +1,8 @@ + + +

        pcb-rnd devlog

        + +

        what's missing for: opengl

        +

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

        pcb-rnd devlog

        + +

        The way forward on cleanup

        +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.3/doc/devlog/20162601/header =================================================================== --- tags/1.2.3/doc/devlog/20162601/header (nonexistent) +++ tags/1.2.3/doc/devlog/20162601/header (revision 8969) @@ -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.3/doc/devlog/20162601/header.csv =================================================================== --- tags/1.2.3/doc/devlog/20162601/header.csv (nonexistent) +++ tags/1.2.3/doc/devlog/20162601/header.csv (revision 8969) @@ -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.3/doc/devlog/20162601/poll.csv =================================================================== --- tags/1.2.3/doc/devlog/20162601/poll.csv (nonexistent) +++ tags/1.2.3/doc/devlog/20162601/poll.csv (revision 8969) @@ -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.3/doc/devlog/20162601/poll.html =================================================================== --- tags/1.2.3/doc/devlog/20162601/poll.html (nonexistent) +++ tags/1.2.3/doc/devlog/20162601/poll.html (revision 8969) @@ -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.3/doc/devlog/20162601/poll.tsv =================================================================== --- tags/1.2.3/doc/devlog/20162601/poll.tsv (nonexistent) +++ tags/1.2.3/doc/devlog/20162601/poll.tsv (revision 8969) @@ -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.3/doc/devlog/20170205_schimp.html =================================================================== --- tags/1.2.3/doc/devlog/20170205_schimp.html (nonexistent) +++ tags/1.2.3/doc/devlog/20170205_schimp.html (revision 8969) @@ -0,0 +1,35 @@ + + +

        pcb-rnd devlog

        + +

        what's needed for schematics -> pcb-rnd

        +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.3/doc/devlog/20170212_ecosys.html =================================================================== --- tags/1.2.3/doc/devlog/20170212_ecosys.html (nonexistent) +++ tags/1.2.3/doc/devlog/20170212_ecosys.html (revision 8969) @@ -0,0 +1,154 @@ + + +

        pcb-rnd devlog

        + +

        The FOS EDA ecosystem and pcb-rnd in it

        + +

        current scene of EDA tools

        +

        +There are some large, proprietary EDA tools out there. Most of them are +monolithic and many of them actively seek legal and technical measures +against free flow of data - as part of the lock-in model, vendors +often prefer users to exclusively use their tool once they started to use +it with a design. It seems most users are happy with this setup. +

        +Sometimes large open source software projects are also built in a monolithic +approach. It sometimes makes it easier for the users of the above proprietary +software to switch to a free tool if the free tool has a similar monolithic +design. However, for smaller, specialized tools, it might be as hard to +join the flow of such a monolithic free tool, as in the flow of a proprietary tool. +Not because of technical measures, but because of how users regard and use +the software.1 +

        +An UNIX approach would be to provide a set of tools each doing a small +part of the job, being able to communicate to each other, and let the user +find the workflows (and combinations) that fit their needs. We already have +such tools available: the gEDA project is a collection of them, but other +projects like QUCS, PetEd, TinyCAD, nicely fit too. But how could a random +selection of unrelated tools, developed independently by different people +compete with an integrated solution? My proposal is: by converting them into +an ecosystem. + +

        An EDA ecosystem

        +

        +The key is to connect all the little tools in meaningful ways. In an ideal +worlds, there would be one universal format (like line based plain text in +UNIX) that all programs could operate on. Unfortunately we are not living in +an ideal world. Still, we could get pairs or even small groups of tools +to temporarily work together by writing converters and import/export modules. +Let's just build random bridges between random tools, without worrying about +how general a given bridge is as long as it fully functions between 2 specific +tools! +

        +The next thing we'd need to do is to present a large number of examples and +tutorials explaining how these flows can be used. This would make it easier +for users to explore the ecosystem and even find new, unexpected ways to use it. +(This obviously won't be appealing for some users who really just prefer +an integrated solution with out-of-the-box icons - but we should just target +the rest of the users with the ecosystem approach.) +

        +Then we should stop worrying about packing and distributing the tools. Let it +be done by professionals, e.g. package maintainers of Linux distributions. When +we write pcb-rnd, we should worry about how we import schematics from TinyCAD, +we should write the import plugin, we should present tutorials and documentations +explaining this flow, but we shouldn't worry too much about how the user gets +TinyCAD in the first place. +

        +We should also give up some of our idealism. As Peter Clifton said in his +2016 FOSDEM talk, this approach would end up in n*n converters for n tools. +But I'd rather have n*n or even n*n/10 converters today than one perfect +interchange tool that covers it all, earliest shipped in 2094. I believe +the hardest part of this is accepting alternatives. Different +projects choose different approaches, different design, different +programming language, different data models. This is not a bad thing, +this is a good thing. This is what gives us alternatives. Unfortunately +this means code duplication, effort duplication, waste of human resources. +But it's still much much cheaper than the loss we'd induce by forcing +everyone to work on and use the One True Solution! That said, I don't +suggest we should just always duplicate everything. I only say that we +should accept the different goals and constraints of different project and +accept that a specific piece of code or data can not always be reused as-is +in another project, even despite of best intention of all parties. +

        +Once we get past our fears of code duplication, and we build the bridges, +we potentially get a large collection of independent utilities. This sort +of joins and pools developer resources too. At the end, the sum of all +developers, users, experience, knowledge, data and code behind such an +ecosystem. even with the overheads subtracted, can overweight of those +behind centralized monolithic projects. This is how it could compete with +those - not on the level of individual tools, but on the level of the whole +ecosystem. +

        +There are well known examples of this setup. To list only two: +

          +
        • the classic UNIX shell tools: shell, grep, sed, awk, tr, make, wc, tail, and a lot more; if we pick one, e.g. grep, and put only that on an alien system (e.g. windows), it is already useful - but it doesn't compete with the native tools found on that system. However, if we consider the whole ecosystem together, it is pretty much competitive. In fact we still use these tools daily. +
        • the ecosystems of each bigger modern scripting languages, such as python, perl, ruby, etc. Users and programmers of these languages heavily depend on the rich set of libraries and modules available. The ecosystem is not the interpreter alone, but the interpreter and the number of independently developed modules written by various individuals. Such ecosystems successfully compete even with commercial "we provide a procedure for every problem" kind of suites. +
        + +

        What we'd need to do for this today

        +

        +Much less than it first seems. +

        +First we need to code the bridges. Do you maintain one of the tools? +Find what other tools can be input to you and code importers on your side. +Find what other tools can use your output and code exporters on your side. +Really, it's that easy. You may want to contact the other tool's team, you +may request and even get assistance, or you can even build a bridge that takes +some coding on both sides. But it is not even required: most of the time, the +simplest import or export module written on one side can solve the problem. +Or write a converter. Can be a simple foo2bar for a single flow, shared as +a mini-tool. If it's useful, it will become the part of the ecosystem. +

        +If you did any of this, you are done with half of the job. We need good PR +or else no one will know about this new bridge. Write a tutorials, blog +posts. Show how this specific bridge can be used in a flow to produce +something useful, even if it is just a blinking LED board. +

        +Let distributions pick up the tools. Let blogs reference your tutorials. Let +3rd party people collect a bunch of tutorials they found useful in a +super-tutorial. When someone asks how to do something exotic on some +public forum, and you know 2..3 tools that can be combined to do it, just +tell them the solution. Don't mind if they'll be a one-time user of the +toolchain, for this single shell pipeline to solve this one problem. + +

        What we are not REQUIRED to do

        +In this section I list what we are not required to do, which doesn't +mean we don't want to do these, or we can't do these or we shouldn't do these. +It only means we could just do the cheap part today and worry about these +tomorrow instead of getting blocked wondering how to solve these. +

        +Centralization: it's not required to have a central organization or +effort to coordinate such an ecosystem in any way. It may be useful to +have such coordination in smaller clusters of the ecosystem, tho, but I +don't think we should worry too much about this at all. If the tools and +tutorials are available, and people found them useful, there would be multiple +independent organizations doing the coordination in parallel - just how a +number of different Linux distributions package the same software, making sure +all pieces work together. Both packaging and getting the packages work together +are totally distribution-specific. +

        +Standardization: e.g. standard, common file formats. Yes, life +would be much easier if we had these already, but we can proceed without +them. Let's waste some time today so we still have users by next week when +we can come up with the common file format multiple tools accept. +

        +Packaging: we don't have to invent our own packaging and distribution +on the ecosystem-level. We don't need to worry how all the tools will land at +the user. As long as each tool is easy to get and installed, let the user do +it, or let 3rd parties (like Linux distributions) do it. We could also +pack up random collections, but it may cause more trouble when it starts to +interfere with local installations or distro installation. + + + +


        +Footnotes: +
        + 1: Some gEDA/PCB users are excited about the new features +in pcb-rnd. They'd switch. When I ask what keeps them back, I often get +this answer: "I'll finish my current design in gEDA/PCB but I will try +pcb-rnd with my next design". Even if pcb-rnd is 100% compatible with gEDA/PCB +for reading .pcb files. I call it the invisible lock-in: we do not +have any technical measures that would keep users from switching between +PCB and pcb-rnd forth and back but they act as if there was. Maybe they +just got used to this lock-in idea too much with other CADs. Index: tags/1.2.3/doc/devlog/20170213_edacore1.html =================================================================== --- tags/1.2.3/doc/devlog/20170213_edacore1.html (nonexistent) +++ tags/1.2.3/doc/devlog/20170213_edacore1.html (revision 8969) @@ -0,0 +1,198 @@ + + +

        pcb-rnd devlog

        + +

        "Edacore" minimum commons

        +

        +History and background: there is a lot happening in pcb-rnd these days. A set +of these seem to nicely connect up and form something that's a big portion +of the edacore idea, just implemented in a different way. We did not have +a grand edacore-like plan behind these, they mostly started to happen +independently. But they really happen to connect that way. In the same time +edacore seems to be in hibernation. When I realized this, I contacted +the edacore people to find out if they are interested in a reboot. +

        +Naming: they haven't yet answered; for the purpose of this document, I'll +use the name "edacore", but I mean it more like a concept than as a project +name or implementation. It may be that it gets realized as a reboot of +the original edacore and it will be the official name; else we will just find +a different name for it. + +

        Acceptance and mutual respect

        +

        +Before we start, we must accept that we have alternative implementations, +different projects going in different directions. Although this means +code and effort duplication, this is not a bad thing, this is a good +thing. Most of us doesn't want to live in a world where there's only +one EDA software available, even if every development effort is concentrated +there. (If you think you do, then rethink it with substituting your favorite +package with one you really dislike and imagine that's the only one available.) +

        +Respecting the choices of another project seems to be simple in theory, but +it is important to see a few examples of what we need to accept in practice. +Else we make decisions tat are unacceptable for one project or another +too easily. An incomplete list of examples of what differs in another EDA project: +

          +
        • It has different goals. Aspects that are extremely important core + concepts here are something to be avoided there. +
        • Different data model. Different way the tool models the world. Even, + different subset of the world is modelled by to tool. +
        • Obviously, different code. This doesn't seem to be a big issue + until a common effort accidentally starts to depend on it, e.g. because + of the lib API. +
        • Different programming languages. Again shouldn't be a big deal, until + you try to provide common code. As edacore spotted too, a plain C lib + seems to be a common minimum for most of the world, but even + there it might be something alien and can easily become a + "why couldn't we just reimplement in OOP/python/ruby/java" question. +
        • Different design choices, even beyond the programming language. + For example pcb-rnd walks the minilib way while gEDA/PCB goes for glib. + This has many consequences: pcb-rnd is more portable, less dependent + on GNU, compiles faster. In return we need to ship the minilibs with it + and if someone joins the project they need to learn the APIs. Both choices + are valid in their domain. If we want do anything common, we must make + it neutral to such choices, else it's automatically locked out from + some projects. +
        +In practice this means if we are to do anything common, shared, we either +accept the ways of the other projects and come up with a minimal common +denominator or the common/shared effort will be refused by some (or even most) +projects we target. This has a few consequences, some requirements we +must obey while designing the common: +
          +
        • It should not interfere with any existing program, code, project +
        • It should not try to push excess amount of new concepts and ways onto + existing projects; there obviously will be some new concepts, as we + are trying to introduce a new shared feature, but it should be actively + kept minimal. +
        • Thus we have to live with the idea of code/effort duplication. E.g. + we implement a common library of footprints - it may be a good idea + to also implement a way to index them and store the result in some + complex data format. But what if the other program already has a + complex data format for this? What if our hash is an incompatible + idea with their lists? It's better to step back and rethink: + do we really have to do the indexing in order to achieve + our goals? If the answer is not "absolutely yes!", we just need + skip it. Less is more. +
        • This obviously includes dependencies. If our shared solution depends + on qt, programs using gtk will hate it. If it depends on glib, + programs using minilibs will hate it. If all documentation and comments + are written in Italian, everyone but Italian projects will hate it. + Just reduce such external dependencies, even if this means less + features. Go for a common minimum instead of "would remove some + code duplications and costs only an extra dependency". +
        • Free/open source means open from ground up, no exceptions. + An open source hardware is not really free if the schematics + comes in a format that's readable only by a proprietary CAD package. + A library or a file format is not free if it is specified by a standard + that can't be included in the same repository for whatever legal + reasons. Yes, this excludes a lot of ISO and STEP and IPC stuff, + and results in effort duplication while we design our own formats. + But there's no point in making a compromise on this and building on + non-free things then see some projects refusing to depend on it + because of the legal implications. +
        + +

        What we could do within these limits?

        +

        +These problems are not new. There are good examples on how people +have solved these in the past - some examples implemented decades +ago and are still widely used in one form or another! The most trivial +of these are network protocols: SMTP, ftp, HTTP, TCP/IP, the IRC protocol, +etc. What's common in them: +

          +
        • They specify a protocol and not the actual implementation. +
        • They are freely accessible as RFCs - no registration, no shopping + carts, no much restrictions; if I wanted to copy the RFC next to my + implementation as a documentation and distribute the pack, I am free + to do so. +
        • They try to concentrate on one thing, specify all relevant details + and leave everything up to the user. +
        +

        +This is a pretty important difference compared to the original edacore +idea (of the 2015 FOSDEM talk). We should try to write a lib and sell +that as the common. Instead, we should: +

          +
        • Define free, open file formats and mechanisms; +
        • Design for the common minimum, not for the fancy extras and completeness. + This format is for interchange, and we want to reach every project, not + just the big, complex ones. If the format requires you to implement + splines, we lock out a bunch of small players with no curve support. + Don't expect interchange formats to be lossless. Don't expect interchange + formats would replace per project native formats. +
        • Preferably design even the file formats and mechanisms in a modular + way, expecting some projects would want to implement only parts of it; + make it work as good as possible in such partial implementations! +
        • As an optional extra we may provide a reference implementation + (code) lib, or even libs. Some projects would use these, embed these, others + would read the source and yet others would totally ignore them. It's + all fine as long as the lib is not the common but is just an appendix. +
        • Provide optional, but out-of-the-box tools. Small, simple, but + useful ones. If we specify a footprint format, provide tools + that parses it, makes checks on it ("lint"), tools that visualize + the footprint (e.g. generate a png). This can be anything from a + web service to command line tools. Best if there are even multiple + interfaces and APIs. This helps projects to adapt the file formats + as they can try it in advance and they see they have debug tools + readily available, still these tools won't interfere with their projects. +
        + +In other words: solve the interchange problem, not the code +duplication problem! + +

        What we don't need to do?

        +

        +We could also do any of these, but to get the project started and be +useful, we are not required to do them. It's an important consideration: +we don't have much resources, we should spend it where it's spent the best. +I believe we don't need to do the below in order to get an "edacore" idea work: +

          +
        • Common code lib implementations; it's a nice extra, but it's the file + format specs that would make it work +
        • Some centralized repository, web service, etc. for sharing user content: + once a few tools already have support for "edacore", this will + automatically happen. Someone, or hopefully even multiple people will + make their public services. Or people will just use github, torrent + or whatever techniques. Of course we can also run + our own repository service but + that should not be tied together with the "edacore" idea, it should just + be one instance that happens to be maintained by the same people who + made up the specs. +
        • "Fancy features". Provide the bare minimum. It's a tradeoff between + the "works everywhere" vs. "looks perfect in all little details". If + the user wants the former, an interchange format is for that; for the + latter, use a native format. +
        + +

        What we could expect from such a project?

        +

        +Assume we designed a set of interchange formats and maybe mechanisms and +we optionally provided some libs and tools. +

          +
        • If we can get at least 2 projects using the new format for exchanging + data, we are at the same point as with the original n*n converter + EDA ecosystem idea. We just + wasted some more time on a yet-another-format. +
        • But if 3 or more projects are using it, we may saved some effort already! +
        • If that happens, users can build and share libraries more easily. +
        • Users will find new ways to combine our tools in the ecosystem - even + unusual ways developers didn't think of, e.g. using schematics cap from + one project and PCB editor from another, even if both projects were + "integrated". +
        + +

        What we should NOT expect from such a project?

        +

        +

          +
        • A common interchange format replacing local native formats +
        • A common interchange format capturing all tiny details that a native + format can +
        • Proprietary EDA tools cooperating on this on the export-side - they + don't want their users to be able to get the design out of their + program, especially not if it's clearly for importing in another +
        • Everyone's support - even with the most careful design and the lowest + barriers there will be project that won't like it and won't join. Some + projects will hate it exactly because it's not restrictive enough, e.g. + that it doesn't mandate OOP or SQL or other specific complexities. +
        Index: tags/1.2.3/doc/devlog/20170213_edacore2.html =================================================================== --- tags/1.2.3/doc/devlog/20170213_edacore2.html (nonexistent) +++ tags/1.2.3/doc/devlog/20170213_edacore2.html (revision 8969) @@ -0,0 +1,57 @@ + + +

        pcb-rnd devlog

        + +

        "Edacore" - extras

        +I believe an edacore-like idea requires only what's described in + this document . Once we have that, +or if we have enough resources, in parallel to that, we could also +develop some extras. This document describes some of those extras. + +

        Services: library repositories

        +
          +
        • a repository is a collection of data files in the interchange + and/or other random formats +
        • there are existing examples out there, including gedasymbols.org + and random cvs, svn, git repositories of users +
        • we shouldn't expect to have a single central service for this; + we may run our own service any time, but it's even better if we design + our formats and tools to let people easily set up their own services +
        • such separately ran and maintained repositories would have different + goals and policies; we shall accept that and be happy about that; we + should distribute file formats and tools, not policies and ideologies. +
        + +

        How my favorite service would look like

        +
          +
        • project-neutral - not a gEDA or KiCad or eagle or qucs or ltspice + library, but a generic user library. If done with converters and/or + interchange formats, neither the originator nor the consumer project + would matter. +
        • optimized for multiple UIs: +
            +
          • CLI access (e.g. through a VCS client) +
          • web access, maybe even web2.0 +
          • remote repo integration (e.g. pcb-rnd has strong support for this) +
          +
        • backed up by a version control system in the background +
        • instead of complex meta-data systems, offer free form tagging, like + openstreetmap does: +
            +
          • tags are free form key=value pairs, both key and value are simple strings +
          • let tagging conventions emerge +
          • let the these conventions be specified and maintained by the user community +
          • do not split the repository on a per uploader basis - that's the least useful information for an end user +
          • maybe implement a separate namespace for "signed" tags; e.g. some registered user would validate a few footprints and would tag them "went on copper and looked good"; if it's a signed tag, end users have the chance to validate the source of the tag and other contributors can not change or overwrite this tag +
          +
        • content licensing: +
            +
          • the ToS would say users must not upload footprints not drawn by themselves +
          • chose 2..3 reasonable licenses and require the user to specify which one the footprint uses upon upload +
          • optionally have a separate distribution and use license +
          +
        • first support footprints and symbols because we have converters for + those; gradually extend to 3d models, FEM, spice, schematics, PCBs + as common formats and/or converters emerge. +
        + Index: tags/1.2.3/doc/devlog/20170405/Makefile =================================================================== --- tags/1.2.3/doc/devlog/20170405/Makefile (nonexistent) +++ tags/1.2.3/doc/devlog/20170405/Makefile (revision 8969) @@ -0,0 +1,2 @@ +umbrella.svg: umbrella.dot + dot -Tsvg umbrella.dot > umbrella.svg \ No newline at end of file Index: tags/1.2.3/doc/devlog/20170405/umbrella.dot =================================================================== --- tags/1.2.3/doc/devlog/20170405/umbrella.dot (nonexistent) +++ tags/1.2.3/doc/devlog/20170405/umbrella.dot (revision 8969) @@ -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.3/doc/devlog/20170405/umbrella.svg =================================================================== --- tags/1.2.3/doc/devlog/20170405/umbrella.svg (nonexistent) +++ tags/1.2.3/doc/devlog/20170405/umbrella.svg (revision 8969) @@ -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.3/doc/devlog/poll_common/gencsv.sh =================================================================== --- tags/1.2.3/doc/devlog/poll_common/gencsv.sh (nonexistent) +++ tags/1.2.3/doc/devlog/poll_common/gencsv.sh (revision 8969) @@ -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.3/doc/devlog/poll_common/gencsv.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/devlog/poll_common/genhtml.sh =================================================================== --- tags/1.2.3/doc/devlog/poll_common/genhtml.sh (nonexistent) +++ tags/1.2.3/doc/devlog/poll_common/genhtml.sh (revision 8969) @@ -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.3/doc/devlog/poll_common/genhtml.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/devlog/poll_common/genpie.sh =================================================================== --- tags/1.2.3/doc/devlog/poll_common/genpie.sh (nonexistent) +++ tags/1.2.3/doc/devlog/poll_common/genpie.sh (revision 8969) @@ -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.3/doc/devlog/poll_common/genpie.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/devlog/res/20150830b_annot.dot =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_annot.dot (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_annot.dot (revision 8969) @@ -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.3/doc/devlog/res/20150830b_annot.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_annot.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_annot.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_annot.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s0.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s0.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s0.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s0.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s1.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s1.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s1.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s2.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s2.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s2.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s3.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s3.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s3.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s4.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s4.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s4.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s4.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s5.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s5.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s5.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s5.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/20150830b_s6.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/devlog/res/20150830b_s6.png =================================================================== --- tags/1.2.3/doc/devlog/res/20150830b_s6.png (nonexistent) +++ tags/1.2.3/doc/devlog/res/20150830b_s6.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/devlog/res/Makefile =================================================================== --- tags/1.2.3/doc/devlog/res/Makefile (nonexistent) +++ tags/1.2.3/doc/devlog/res/Makefile (revision 8969) @@ -0,0 +1,4 @@ +all: 20150830b_annot.png + +%.png: %.dot + dot -Tpng < $^ > $@ Index: tags/1.2.3/doc/doc.html =================================================================== --- tags/1.2.3/doc/doc.html (nonexistent) +++ tags/1.2.3/doc/doc.html (revision 8969) @@ -0,0 +1,36 @@ + + + + pcb-rnd - news + + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +
            + +

            pcb-rnd documentation

            + + + + + Index: tags/1.2.3/doc/features/ba.html =================================================================== --- tags/1.2.3/doc/features/ba.html (nonexistent) +++ tags/1.2.3/doc/features/ba.html (revision 8969) @@ -0,0 +1,70 @@ + + + + pcb-rnd - back annotation + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [ba] patches

            +Back annotation was a long standing missing functionality. There has been +different suggestions, including: +
              +
            • back annotation is not needed at all, the user can do it manually +
            • pcb should generate a new netlist, the user should run diff on the netlists and manually edit the schematics +
            • gschem should be able to load netlists emitted by PCB; or gnetlist could reverse-process such a netlist +
            +

            +The current implementation allows pcb-rnd users to make deliberate pin +swapping and footprint replacement. The changes can be saved in a +"netlist patch" format. A modified gschem can load these and present them +as search results pointing to parts of the schematics that need to be changed. +There is a +demo video about how this happens in practice. +

            +The modified gschem can be checked out from svn://repo.hu/geda-gaf-ba/trunk +

            +The underlying mechanism is versatile and potentially allows more changes +to be back annotated. These are not yet accessible due to the lack of PCB +actions and GUI. + +

            Design decisions

            +This devlog entry functions +as a design decision document. + Another entry is a summary +on how the feature ended up in a private feature-fork of gschem. + +

            save/load and compatibility

            +Deliberate changes are tracked so that a new forward annotation from +the old schematics won't break them. To do this, pcb-rnd saves a +NetListPatch() section in the file. Mainline PCB can not handle this section. +Compatibility, by use case: +
              +
            • 1. No back annotation is made in pcb-rnd: the file stays compatible +
            • 2. Back annotation is made in pcb-rnd, then the changes are done on the schematics and a forward annotation is also done: the netlist patch in pcb-rnd becomes empty so the pcb file is again compatible with mainline pcb; this is called resolution of netlist patches +
            • 3. There are unresolved netlist patches saved in pcb-rnd and the user attempts to load the pcb file in mainline pcb: syntax error (but no data loss); solution: resolve the netlist patch as described in point 2. +
            • 4. Cheat for situation 3.: manually remove the NetListPatch() section from the save file. This way the back annotation info is lost, but mainline pcb can load the file again. This action is sort of "revert back annotation". +
            • 5. Any file saved by mainline PCB can be opened by pcb-rnd, back annotation does not affect that. + +
            + + +

            plans

            +Back annotation for further changes, e.g. value change, naming/renaming nets, +etc. + + Index: tags/1.2.3/doc/features/cycdrag.html =================================================================== --- tags/1.2.3/doc/features/cycdrag.html (nonexistent) +++ tags/1.2.3/doc/features/cycdrag.html (revision 8969) @@ -0,0 +1,48 @@ + + + + pcb-rnd - [cycdrag] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [cycdrag] patches

            + +A long standing misfeature of pcb (and pcb-rnd) has been that when dragging the +end of connected traces, pcb chosen one of the traces "randomly". It often +didn't pick the one the user wanted to move. The workaround was to move the +one that pcb picked and then return and move the target trace then +move the other trace back. This gets even more annoying if there are more than +two objects connected in the given point: 3 traces and a via for example. +

            +The cycdrag patch addresses this issue by defining an action that can cycle +through objects that could be dragged in the given point while the left mouse +button is pressed. This lets the user explicitly select the one object to +work on. +

            +This demo video +demonstrates how it works with three lines and a via. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +It does not work with the lesstif HID. It does not work with the rubber band +mode. + + + Index: tags/1.2.3/doc/features/debian.html =================================================================== --- tags/1.2.3/doc/features/debian.html (nonexistent) +++ tags/1.2.3/doc/features/debian.html (revision 8969) @@ -0,0 +1,66 @@ + + + + pcb-rnd - [debian] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/debian_list.html =================================================================== --- tags/1.2.3/doc/features/debian_list.html (nonexistent) +++ tags/1.2.3/doc/features/debian_list.html (revision 8969) @@ -0,0 +1,67 @@ + + + + + + pcb-rnd - Debian package list + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/dynstyle.html =================================================================== --- tags/1.2.3/doc/features/dynstyle.html (nonexistent) +++ tags/1.2.3/doc/features/dynstyle.html (revision 8969) @@ -0,0 +1,40 @@ + + + + pcb-rnd - [dynstyle] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/flagcomp.html =================================================================== --- tags/1.2.3/doc/features/flagcomp.html (nonexistent) +++ tags/1.2.3/doc/features/flagcomp.html (revision 8969) @@ -0,0 +1,43 @@ + + + + pcb-rnd - [flagcomp] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/fp_wget.html =================================================================== --- tags/1.2.3/doc/features/fp_wget.html (nonexistent) +++ tags/1.2.3/doc/features/fp_wget.html (revision 8969) @@ -0,0 +1,61 @@ + + + + pcb-rnd - [fp_wget] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [fp_wget] patch

            + +Since version 1.0.10, pcb-rnd implements a new footprint mechanism (see +[fp_fs] and [library_t]). +The new code allows footprint backend plugins to get library from anywhere. +The [fp_wget] plugin is an implementation that: +
              +
            • downloads a library list from the web on startup into a local cache +
            • downloads footprints from the web on-demand into a local cache +
            +

            +This is all transparent, the user experience is that the remote library is +like a read-only local library reachable from the library window. Since +version 1.2.2, automatic index update is controlled by a configuration setting +and a selective, per website mecahnism for manual triggered update. +

            +A web site used as a library should be able to: +

              +
            • generate a plain text list of all footprints available +
            • return the raw footprint file by name +
            +

            +The plugin uses external program wget to communicate on the web. + + +

            How to configure for eakrill

            +Add wget@edakrill in the library search path (e.g. in preferences as library-newlib). + +

            How to configure for gedasymbols.org

            +Add wget@gedasymbols in the library search path (e.g. in preferences as library-newlib). + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Better feedback on progress, refresh in the background. + + + Index: tags/1.2.3/doc/features/fullscreen.html =================================================================== --- tags/1.2.3/doc/features/fullscreen.html (nonexistent) +++ tags/1.2.3/doc/features/fullscreen.html (revision 8969) @@ -0,0 +1,40 @@ + + + + pcb-rnd - full screen gtk + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - full screen gtk

            +On small screen the overhead of the menu line, bottom status line and left +layer selection bar is just too expensive. Since 1.1.2, the gtk hid can +be switched between the usual setup and a so called "full screen mode" +where most widgets are hidden, leaving much more screen space to the +editor widget. There's a FullScreen() action that can set or toggle +the state and a default key binding in gtk on the backslash ('\') to +toggle it. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Make hiding various parts of the GUI configurable. No plans to implement +it for the lesstif HID. + + + Index: tags/1.2.3/doc/features/gpmi.html =================================================================== --- tags/1.2.3/doc/features/gpmi.html (nonexistent) +++ tags/1.2.3/doc/features/gpmi.html (revision 8969) @@ -0,0 +1,60 @@ + + + + pcb-rnd - [gpmi] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/grid.html =================================================================== --- tags/1.2.3/doc/features/grid.html (nonexistent) +++ tags/1.2.3/doc/features/grid.html (revision 8969) @@ -0,0 +1,101 @@ + + + + pcb-rnd - gtk grid fixes + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - gtk grid fixes

            + +

            Problem with the original gtk grid

            + +The original code draws every grid point on screen, even the ones that are +off the board. When the user zooms out with a dense grid, it can become too +dense - the original code turns the grid off in this case. +

            +If the grid is very dense, on a large screen the software render may slow down. +This is noticeable in pan and zoom mostly. The bottleneck is the gtk call +that draws the grid points: if there are too many of them, it's slow. + + +

            New grid

            + +To overcome this problem, pcb-rnd offers configuration settings to limit +the number of dots to be drawn. There are mainly two parallel approaches: +using a local grid or draw less dots in a global grid. The +old code defined only a global grid and did not have runtime settings for +the properties of the grid. +

            +There's a new "Grid properties" submenu in the view menu in the default +gtk hid menu file. Screenshots were taken with this menu teared-down to +demonstrate the settings. + +

            Global grid improvements

            + +The most trivial optimization is that grid points off the board are simply +not drawn: +

            +[screenshot showing of grid] +

            +Next, the compile-time configurable "minimum distance between grid points +before it is too dense" setting is user configurable now. The default value +can be changed in any of the usual +configuration sources. However, +when the configured density is reached while zooming out, there are two options. +

            +The first, default option is to do the same that the original code did: just +hide the grid: +

            +[screenshot with grid option menu] +

            +An alternative is to use sparse global grid which means only +every 2nd, 3rd, 4th, ... Nth grid point is drawn. The cursor still snaps +to every real grid point, so the grid got sparse only on the display. Note +how the line is drawn on invisible grid points: +

            +[screenshot with grid option menu] + +

            Introduction of the local grid

            +Another approach is to use a local grid. The grid helps finding whether +existing objects are aligned or where the next move/click would end up. +These are usually interesting only in a small range around the crosshair and +less interesting on the other end of the board. Local grid draws the grid +points only near the crosshair. Such local grid follows the crosshair +everywhere: +

            +[screenshot with grid option menu] +

            +The user can configure or interactively set the radius in which the grid +points are drawn: +

            +[screenshot with grid option menu] +

            +The radius is given in "number of grid points", thus the local grid yields +a constant number of points that is independent of the actual grid size. When +a local grid gets too dense, it is hidden - there's no sparse option, since +local grids usually have too few points to make reasonable skips. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +This feature is gtk-specific and is complete. There are no plans to +implement this in the lesstif HID at the moment. + + + Index: tags/1.2.3/doc/features/grid_edge.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/grid_edge.png =================================================================== --- tags/1.2.3/doc/features/grid_edge.png (nonexistent) +++ tags/1.2.3/doc/features/grid_edge.png (revision 8969) Property changes on: tags/1.2.3/doc/features/grid_edge.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/grid_global_nosparse.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/grid_global_nosparse.png =================================================================== --- tags/1.2.3/doc/features/grid_global_nosparse.png (nonexistent) +++ tags/1.2.3/doc/features/grid_global_nosparse.png (revision 8969) Property changes on: tags/1.2.3/doc/features/grid_global_nosparse.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/grid_global_sparse.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/grid_global_sparse.png =================================================================== --- tags/1.2.3/doc/features/grid_global_sparse.png (nonexistent) +++ tags/1.2.3/doc/features/grid_global_sparse.png (revision 8969) Property changes on: tags/1.2.3/doc/features/grid_global_sparse.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/grid_local_16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/grid_local_16.png =================================================================== --- tags/1.2.3/doc/features/grid_local_16.png (nonexistent) +++ tags/1.2.3/doc/features/grid_local_16.png (revision 8969) Property changes on: tags/1.2.3/doc/features/grid_local_16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/grid_local_4.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/grid_local_4.png =================================================================== --- tags/1.2.3/doc/features/grid_local_4.png (nonexistent) +++ tags/1.2.3/doc/features/grid_local_4.png (revision 8969) Property changes on: tags/1.2.3/doc/features/grid_local_4.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/index.html =================================================================== --- tags/1.2.3/doc/features/index.html (nonexistent) +++ tags/1.2.3/doc/features/index.html (revision 8969) @@ -0,0 +1,63 @@ + + + + pcb-rnd - features + + + + + + + + + +
            Main + News + Doc + 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 +
            [mincut] minimal cut based warnings on shorts +
            [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 +
            [pcb-fp] generic parametric footprints; on-the-fly footprint generation by external tools written in any language (remove m4 hardwirings) +
            [pcblib], [fp_fs], + [pcblib-param] clean up the footprint library shipped +
            [library_t] footprint library is an arbitrary tree instead of a special, 2 level tree +
            [fp_wget] web based footprint libraries, integration of gedasymbols.org +
            [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 +
            [ba] back annotation +
            [onpoint] on-point by Robert Drehmel +
            [cycdrag] cycle drag; with additional feature: negative box select +
            [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 +
            [propedit] property/attribute editor (gtk) +
            [oldplugins] import old PCB plugins +
            [query] query language +
            routing styles routing style fixes +
            (gtk grid) gtk grid improvements: sparse global grids, local grids +
            (full screen) gtk full screen edit mode +
            (settings) minor changes in default settings + + + +
            + + + Index: tags/1.2.3/doc/features/intconn.html =================================================================== --- tags/1.2.3/doc/features/intconn.html (nonexistent) +++ tags/1.2.3/doc/features/intconn.html (revision 8969) @@ -0,0 +1,92 @@ + + + + pcb-rnd - [intconn] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/intconn1.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/intconn1.png =================================================================== --- tags/1.2.3/doc/features/intconn1.png (nonexistent) +++ tags/1.2.3/doc/features/intconn1.png (revision 8969) Property changes on: tags/1.2.3/doc/features/intconn1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/intconn2.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/intconn2.png =================================================================== --- tags/1.2.3/doc/features/intconn2.png (nonexistent) +++ tags/1.2.3/doc/features/intconn2.png (revision 8969) Property changes on: tags/1.2.3/doc/features/intconn2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/intconn3.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/intconn3.png =================================================================== --- tags/1.2.3/doc/features/intconn3.png (nonexistent) +++ tags/1.2.3/doc/features/intconn3.png (revision 8969) Property changes on: tags/1.2.3/doc/features/intconn3.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/io.html =================================================================== --- tags/1.2.3/doc/features/io.html (nonexistent) +++ tags/1.2.3/doc/features/io.html (revision 8969) @@ -0,0 +1,43 @@ + + + + pcb-rnd - [io_*] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/jumper_1206.fp =================================================================== --- tags/1.2.3/doc/features/jumper_1206.fp (nonexistent) +++ tags/1.2.3/doc/features/jumper_1206.fp (revision 8969) @@ -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.3/doc/features/library_t.html =================================================================== --- tags/1.2.3/doc/features/library_t.html (nonexistent) +++ tags/1.2.3/doc/features/library_t.html (revision 8969) @@ -0,0 +1,48 @@ + + + + pcb-rnd - [library_t] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [library_t] patch

            + +The original code has a special setup for representing trees, C structures +called LibraryMenu and LibraryEntry. This system can represent only a subset +of trees: there is a root, a level consist of directories only and a next level, +each directory consist of data nodes only. This has been enough for newlib, +which strictly follows this model in the file system hierarchy. The lesstif +HID also hardwired this model in the GUI. +

            +In pcb-rnd this has been replaced with a new struct type called library_t +that can represent an arbitrary tree: directories and files within directories +down to many levels. +

            +Both the gtk and the lesstif had has been modified accordingly and can +properly display the tree. This in turn enables alternative footprint backend +implementations such as fp_wget to import +more complex libraries, e.g. the one on gedasymbols.org. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Finished, no plans. + + + Index: tags/1.2.3/doc/features/mincut.html =================================================================== --- tags/1.2.3/doc/features/mincut.html (nonexistent) +++ tags/1.2.3/doc/features/mincut.html (revision 8969) @@ -0,0 +1,67 @@ + + + + pcb-rnd - [mincut] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [mincut] patch

            + +The original code was highlighting pins/pads only when a short came around +after rats nest optimization. This was not very helpful on a complex board. +There had been a long discussion on the mailing list about the best solutions. +There were a few very good ideas, including: +
              +
            • manual tagging of objects (lines, polys, arcs, vias) with net and warn + where two differently tagged net connects +
            • automatic tagging based on "where it was connected first", then the same + warning mechanism as above +
            • trace history (using the undo buffer?) and go back until when it was + not broken, check what exactly broke it +
            • history combined with tagging +
            • calculate minimal cut +
            +

            +I choose minimal cut for my patch because it doesn't require tracing the +full history or any manual administration of nets vs. objects (which I +would find inevitable even with manual tagging - directly or indirectly +the user needs to be able to change net tags). +

            +The minimal cut is the least amount of object whose removal would resolve +the short. It is best demonstrated on an example: +

            +[Six simple layouts, one correct and five with shorted nets] +

            +Removing all the marked lines/polys/vias would surely resolve the short +(sometimes leaving rat lines behind). Minimal cut is better than randomly +removing objects, tho: it guarantees that the minimal amount of objects +are to be removed. On a complex board, this place is likely to be close +to the place where the problem really is - much closer than the pins/pads. +

            +Since mincut can be expensive on large boards, the feature can be enabled +per board (a new PCB flag) and can be disabled globally (--enable-mincut 0 +when starting PCB). + +

            save/load and compatibility

            +New PCB flag enablemincut. Mainline pcb ignores this flag but does not +preserve it. + +

            plans

            +Finished, no plans. + + Index: tags/1.2.3/doc/features/mincut.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/mincut.png =================================================================== --- tags/1.2.3/doc/features/mincut.png (nonexistent) +++ tags/1.2.3/doc/features/mincut.png (revision 8969) Property changes on: tags/1.2.3/doc/features/mincut.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/negselect.html =================================================================== --- tags/1.2.3/doc/features/negselect.html (nonexistent) +++ tags/1.2.3/doc/features/negselect.html (revision 8969) @@ -0,0 +1,51 @@ + + + + pcb-rnd - negative box select + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [cycdrag] patches, negative box select

            + +When a selection is made using drag&drop (box selection), depending +on the direction the rule for object selection differ: +
              +
            • drag from top-left towards bottom-right (positive sized box): + select objects that are fully contained in the box (original behaviour) +
            • drag in any other direction (e.g. bottom-left to top-right, or + bottom-right to top-left; negative sized box): + select objects that are even partially within the box or merely touch + the edge of the box +
            + +The feature can be disabled using the editor/selection/disable_negative conf +setting. +

            +It's possible to limit the feature so that only horizontal-negative is +considered negative size (i.e. only right-to-left dragging), using the +editor/selection/symmetric_negative conf setting. + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Work more on some rough corners of the negative direction: e.g. pads are +handled as 0 width lines so the selection has to hit the center. + + + Index: tags/1.2.3/doc/features/nonetlist.html =================================================================== --- tags/1.2.3/doc/features/nonetlist.html (nonexistent) +++ tags/1.2.3/doc/features/nonetlist.html (revision 8969) @@ -0,0 +1,73 @@ + + + + pcb-rnd - [nonetlist] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/oldplugins.html =================================================================== --- tags/1.2.3/doc/features/oldplugins.html (nonexistent) +++ tags/1.2.3/doc/features/oldplugins.html (revision 8969) @@ -0,0 +1,71 @@ + + + + pcb-rnd - [oldplugins] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [oldplugins]

            + +In this effort I imported a set of old PCB plugins to be core plugins of +pcb-rnd. This will make it easier to keep them up to date, to defeat +the bitrot effect. The feature plugins that got imported so far: +
              +
            • autocrop +
            • boardflip +
            • distalign +
            • distaligntext +
            • jostle - doesn't work properly +
            • polycombine +
            • polystich - segfaults +
            • teardrops +
            • renumberblock - as part of the renumber plugin +
            • smaprtdisperse +
            +

            +The import/export plugins imported over the default set of the last official +mainline release: +

              +
            • import_dsn - specctra importer - compiles, parser needs a full rewrite, it tries to read an s-expression line by line with fgets() +
            • export_dsn - specctra exporter - compiles, produces valid-looking output - need tester to validate the output +
            • export_bboard - breadboard exporter - compiles, produces valid-looking output - need tester +
            • export_dxf - mechanical cad export - compiles, missing header data renders exported files unusable +
            • export_ipcd356 - electrical test output - compiles, produces valid-looking output - need tester +
            • export_openscad - 3d modeling - compiles, output sort of works, models not yet imported, need tester +
            + +Plugins that won't be imported: +
              +
            • findelement - [query] takes care of that +
            • findrat - [query] will take care of that +
            • join-found - not clear what it would do +
            • lockelements - [query] can select elements then SetFlag() should be able to lock them +
            • sedrename - [query] will take care of that +
            • upth2pth - [query] will take care of that +
            • ratsel - written in C++ +
            • stipple - written in C++ +
            + +

            save/load and compatibility

            +Not affected. + +

            plans

            +Any interesting plugin is subject to be imported. + + + Index: tags/1.2.3/doc/features/onpoint.html =================================================================== --- tags/1.2.3/doc/features/onpoint.html (nonexistent) +++ tags/1.2.3/doc/features/onpoint.html (revision 8969) @@ -0,0 +1,70 @@ + + + + pcb-rnd - [onpoint] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [onpoint] patches

            + +Robert Drehmel writes: +
            +When (e.g.) routing 5mm power traces on a small grid, it's not always easy to hit the
            +point where the trace ended (which is the center of the semicircle at the end of the
            +line) to start the next line.  If you have selected the line tool, finding the end of
            +the line can become guesswork as the cursor doesn't change shape like it does with the
            +select tool.
            +I want my traces to consist of lines and arcs that are perfectly connected and I want
            +to work as fast as possible.
            +
            +Attached is a small patch that
            +
            +  - makes it possible to deactivate snapping to "some sensible point along a line".
            +    (that's what a comment in the code says). This snapping algorithm gets in the way
            +    sometimes so you have to slowly go over a line to find out where it really ends,
            +    bouncing back and forth between the points of the small grid, the end of the line
            +    and these "sensible points", which is wasting time. The command is
            +    "Display(ToggleSnapOffGridLine)". It is still activated by default to avoid
            +    violating POLA.
            +
            +  - more importantly, introduces a new command called "Display(ToggleHighlightOnPoint)"
            +    that highlights all lines and arcs which have (end)points exactly on the position
            +    where the cross hair is currently snapped to. It therefore helps finding the end
            +    points of lines and arcs, but sometimes also shows redundant traces, traces that
            +    aren't perfectly connected to each other, traces that don't end directly on the
            +    center of a via but should, etc. It works with thin draw too and I tested it with
            +    gtk and lesstif.
            +
            +I use the second option mostly in conjunction with deactivating the first. Both commands
            +have been added to the menu by means of (g)pcb-menu.res.in and are available as command
            +line options as well.
            +Caveats:
            +  - The HID API expects all HIDs to make a copy of the color string when setting a color.
            +  - The function that lightens up a color could be improved.
            +  - I used it for a while, but after porting it from my local fork, it probably needs
            +    more testing.
            +
            + +

            save/load and compatibility

            +Not affected. + +

            plans

            +The feature is complete. + + + Index: tags/1.2.3/doc/features/pcb-fp.html =================================================================== --- tags/1.2.3/doc/features/pcb-fp.html (nonexistent) +++ tags/1.2.3/doc/features/pcb-fp.html (revision 8969) @@ -0,0 +1,56 @@ + + + + pcb-rnd - [pcb-fp] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [pcb-fp] patch

            + +Pcb-fp is an effort to clean up the footprint situation: +
              +
            • replace lib and newlib with pcblib, a library that tries to provide common footprints only +
            • clear the syntax: if a footprint name contains parenthesis, it's generated (parametric footprint), else it's the name of a static footprint file +
            • parametric footprints: replace m4 with a generic, language-independent footprint generator framework +
                +
              • implement libpcb_fp, which centralizes searching and loading footprints +
              • fork gsch2pcb to gsch2pcb-rnd that does not have any m4 references hardwired +
              • fork gnet_gsch2pcb.scm (the gnetlist backend) to remove m4 heuristics +
              +
            + +

            Example

            +Interactive parametric footprint selection in pcb-rnd: +

            +[screenshot of footprint select menu, with preview] +

            +An online footprint generator web1.0 version is also available. + +

            save/load and compatibility

            +Save/load files are not affected. If a schematics is written for the new +library and depends on parametric footprints: +
              +
            • mainline gsch2pcb won't find those footprints +
            • mainline pcb won't show those footprints in the footprint selection dialog +
            + +

            plans

            +No plans - this feature is fully implemented. + + + Index: tags/1.2.3/doc/features/pcb-fp.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/pcb-fp.png =================================================================== --- tags/1.2.3/doc/features/pcb-fp.png (nonexistent) +++ tags/1.2.3/doc/features/pcb-fp.png (revision 8969) Property changes on: tags/1.2.3/doc/features/pcb-fp.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/pcblib.html =================================================================== --- tags/1.2.3/doc/features/pcblib.html (nonexistent) +++ tags/1.2.3/doc/features/pcblib.html (revision 8969) @@ -0,0 +1,76 @@ + + + + pcb-rnd - [pcblib] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [pcblib] and [pcblib-param] and [fp_fs] patches

            + +
            +The footprint library shipped with mainline pcb is cluttered with +special purpose parts. I believe PCB encourages the user from +an early stage to build his own library. Thus the purpose of +the library shipped with PCB should be +to provide a minimal collection of real essential footprints ... +
              +
            • ... for the very beginning of the learning curve; +
            • ... and to be the core of the user's own library later. +
            +

            +[pcblib] is a replacement of newlib/ and lib/ and the m4 macros with +such an essential core library of static footprints ("file elements") +and easier-to-use parametric footprints. +

            +There is an online map of +the library and +an online interface to the parametric footprint generators. + +

            Design decisions

            +Parts are sorted only in a few directories: smd, thru-hole, connector and +parametric. I believe there are so many orthogonal properties of footprints +that there's no obvious hierarchy. Also, pcblib contains much fewer footprints +than newlib so it should be still easy to navigate. +

            +Parametric footprints are in a separate directory for now, even tho they +would fit under smd, thru-hole or connector. The reason is purely historical +and the layout may change in the future. + +

            Example

            +To the right: Footprint selection dialog on pcblib, with the smd directory +open. Note how few smd parts are there. Still, smd/ is the most crowded +subdirectory! + +

            [fp_fs]

            +As of version 1.0.10, the footprint list/search/load of footprints is a plugin. +The original code that handles local file system footprint libraries (e.g. +pcblib or newlib) is now a plugin. Alternative plugins can be provided that work +from databases or from the web. In extreme +situations the file system based footprint plugin can even be disabled. + +

            save/load and compatibility

            +Not affected: elements are embedded in the PCB. + +

            plans

            +None, the feature is complete. +
                        + +[screenshot of footprint select menu, with preview] +
            + + Index: tags/1.2.3/doc/features/pcblib.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/pcblib.png =================================================================== --- tags/1.2.3/doc/features/pcblib.png (nonexistent) +++ tags/1.2.3/doc/features/pcblib.png (revision 8969) Property changes on: tags/1.2.3/doc/features/pcblib.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/polygrid.html =================================================================== --- tags/1.2.3/doc/features/polygrid.html (nonexistent) +++ tags/1.2.3/doc/features/polygrid.html (revision 8969) @@ -0,0 +1,37 @@ + + + + pcb-rnd - [polygrid] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/propedit.html =================================================================== --- tags/1.2.3/doc/features/propedit.html (nonexistent) +++ tags/1.2.3/doc/features/propedit.html (revision 8969) @@ -0,0 +1,67 @@ + + + + pcb-rnd - [propedit] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - [propedit]

            +Since 1.1.2, pcb-rnd core is able to attach user defined attributes +(arbitrary textual key=value pairs) to any object. The original mainline +pcb-rnd was forked from already supported attributes on some objects (e.g. +board attributes, net attributes) but not on all. However, the user had +very little access to the attributes - no GUI or action would handle them. +

            +Propedit introduces a property editor window in gtk that is able to +edit attributes and core properties of all selected objects. Core properties +include all hardwired properties of objects, such as geometry (e.g. +trace width, hole diameter, clearance) or textual data (e.g. string of +a text). +

            +[screenshot of Edit Properties menu] +

            +Properties and attributes of the selected objects are collected in a +sorted list - each row of the list is a property (starting with p/) or +an attribute (starting with a/). For each row all values seen in the selection +are also collected so that the following values can be presented on the list, +per row: +

              +
            • the most common value +
            • minimum value (for numeric value types) +
            • maximum value (for numeric value types) +
            • average value (for numeric value types) +
            +

            +When the user clicks on a row, an edit box is activated and the value can +be changed. A combo box lists all existing values for the given row, so +it is easy to unify the value of a property or attribute among all selected +objects to one of the existing values, but the user is also free to enter +a new value. +

            +It is also possible to remove existing attributes or to add new attributes. + +

            save/load and compatibility

            +Attributes of most objects can not be saved in the original .pcb format. +The propedit feature is most useful when used with the lihata board format. + +

            plans

            +Various improvements. Currently there's no plan to make this function available +in the lesstif HID. + + + Index: tags/1.2.3/doc/features/propedit.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/propedit.png =================================================================== --- tags/1.2.3/doc/features/propedit.png (nonexistent) +++ tags/1.2.3/doc/features/propedit.png (revision 8969) Property changes on: tags/1.2.3/doc/features/propedit.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/query.html =================================================================== --- tags/1.2.3/doc/features/query.html (nonexistent) +++ tags/1.2.3/doc/features/query.html (revision 8969) @@ -0,0 +1,44 @@ + + + + pcb-rnd - [query] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/res.html =================================================================== --- tags/1.2.3/doc/features/res.html (nonexistent) +++ tags/1.2.3/doc/features/res.html (revision 8969) @@ -0,0 +1,149 @@ + + + + pcb-rnd - [res] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/routings.html =================================================================== --- tags/1.2.3/doc/features/routings.html (nonexistent) +++ tags/1.2.3/doc/features/routings.html (revision 8969) @@ -0,0 +1,99 @@ + + + + pcb-rnd - routing style fixes + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/scconfig.html =================================================================== --- tags/1.2.3/doc/features/scconfig.html (nonexistent) +++ tags/1.2.3/doc/features/scconfig.html (revision 8969) @@ -0,0 +1,35 @@ + + + + pcb-rnd - [scconfig] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/settings.html =================================================================== --- tags/1.2.3/doc/features/settings.html (nonexistent) +++ tags/1.2.3/doc/features/settings.html (revision 8969) @@ -0,0 +1,51 @@ + + + + pcb-rnd - different default settings + + + + + + + + + +
            Main + News + Doc + 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.3/doc/features/square.html =================================================================== --- tags/1.2.3/doc/features/square.html (nonexistent) +++ tags/1.2.3/doc/features/square.html (revision 8969) @@ -0,0 +1,91 @@ + + + + pcb-rnd - [square] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [square] patch

            +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.3/doc/features/square.pcb =================================================================== --- tags/1.2.3/doc/features/square.pcb (nonexistent) +++ tags/1.2.3/doc/features/square.pcb (revision 8969) @@ -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.3/doc/features/square.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/features/square.png =================================================================== --- tags/1.2.3/doc/features/square.png (nonexistent) +++ tags/1.2.3/doc/features/square.png (revision 8969) Property changes on: tags/1.2.3/doc/features/square.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/features/tostyle.html =================================================================== --- tags/1.2.3/doc/features/tostyle.html (nonexistent) +++ tags/1.2.3/doc/features/tostyle.html (revision 8969) @@ -0,0 +1,70 @@ + + + + pcb-rnd - [tostyle] + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd - the [tostyle] patch

            + +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.3/doc/features/unglib.html =================================================================== --- tags/1.2.3/doc/features/unglib.html (nonexistent) +++ tags/1.2.3/doc/features/unglib.html (revision 8969) @@ -0,0 +1,37 @@ + + + + pcb-rnd - [unglib] + + + + + + + + + +
            Main + News + Doc + 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.3/doc/help.html =================================================================== --- tags/1.2.3/doc/help.html (nonexistent) +++ tags/1.2.3/doc/help.html (revision 8969) @@ -0,0 +1,66 @@ + + + + pcb-rnd - help wanted + + + + + + + + + + +
            Main + News + Doc + 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 geda user reference output valudation (gerber and other formats) +
            tutorial geda user tutorial projects +
            windows geda user generic testing on windows +
            mtest geda user systematic manual testing +
            doc geda 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.3/doc/index.html =================================================================== --- tags/1.2.3/doc/index.html (nonexistent) +++ tags/1.2.3/doc/index.html (revision 8969) @@ -0,0 +1,133 @@ + + + + pcb-rnd - main + + + + + + + + + + +
            Main + News + Doc + 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 +

            historically is a fork of PCB +

            is an informal part of the geda project + +

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

            +
            + +
            RaNDom + When it started, it used to be a random collection of small fixes and improvements. We got much further than that by now. +
            + +

            + + + +
            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.3/doc/irc.html =================================================================== --- tags/1.2.3/doc/irc.html (nonexistent) +++ tags/1.2.3/doc/irc.html (revision 8969) @@ -0,0 +1,46 @@ + + + + pcb-rnd - IRC + + + + + + + + + + +
            Main + News + Doc + 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.3/doc/keys.html =================================================================== --- tags/1.2.3/doc/keys.html (nonexistent) +++ tags/1.2.3/doc/keys.html (revision 8969) @@ -0,0 +1,710 @@ + + + + + + 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) +
            / + Cycle Clip
            Display(CycleClip) +
            Cycle Clip
            Display(CycleClip) +
            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) +
            =-shift + 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) +
            ] + 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 text 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-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.3/doc/keys_mkey.html =================================================================== --- tags/1.2.3/doc/keys_mkey.html (nonexistent) +++ tags/1.2.3/doc/keys_mkey.html (revision 8969) @@ -0,0 +1,530 @@ + + + + + + Key to action bindings + + + + + +

            Key to action bindings

            + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
            key pcb-menu-mkey.lht +
            . + 'All-direction' lines
            conf(toggle, editor/all_direction_lines, design) +
            / + Cycle Clip
            Display(CycleClip) +
            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 + 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 + 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 + 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 + 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 + 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) +
            =-shift + Auto-Optimize
            djopt(auto) +
            [ + Grid -5mil
            SetValue(Grid,-5,mil) +
            \ + Full screen
            fullscreen(toggle) +
            ] + 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) +
            b + Flip Object
            Flip(Object) +
            b-alt-ctrl + 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 +
            Buffer/Mirror buffer (up/down)
            Mode(PasteBuffer); PasteBuffer(Mirror) +
            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) +
            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) +
            f
             a +
            Save Layout As...
            Save(LayoutAs) +
            f
             c +
            Quit Program
            Quit() +
            f
             i +
            Export layout...
            ExportGUI() +
            f
             n +
            Start New Layout
            New() +
            f
             o +
            Load layout
            Load(Layout) +
            f
             p +
            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() +
            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 + 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-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(AddSelected); RemoveSelected(); 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.3/doc/license.html =================================================================== --- tags/1.2.3/doc/license.html (nonexistent) +++ tags/1.2.3/doc/license.html (revision 8969) @@ -0,0 +1,55 @@ + + + + pcb-rnd - license + + + + + + + + + + +
            Main + News + Doc + 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.3/doc/mac.txt =================================================================== --- tags/1.2.3/doc/mac.txt (nonexistent) +++ tags/1.2.3/doc/mac.txt (revision 8969) @@ -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.3/doc/man/Makefile =================================================================== --- tags/1.2.3/doc/man/Makefile (nonexistent) +++ tags/1.2.3/doc/man/Makefile (revision 8969) @@ -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.3/doc/man/README =================================================================== --- tags/1.2.3/doc/man/README (nonexistent) +++ tags/1.2.3/doc/man/README (revision 8969) @@ -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.3/doc/man/copyright.mml =================================================================== --- tags/1.2.3/doc/man/copyright.mml (nonexistent) +++ tags/1.2.3/doc/man/copyright.mml (revision 8969) @@ -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.3/doc/man/fp2anim.1 =================================================================== --- tags/1.2.3/doc/man/fp2anim.1 (nonexistent) +++ tags/1.2.3/doc/man/fp2anim.1 (revision 8969) @@ -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.3/doc/man/fp2anim.1.html =================================================================== --- tags/1.2.3/doc/man/fp2anim.1.html (nonexistent) +++ tags/1.2.3/doc/man/fp2anim.1.html (revision 8969) @@ -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.3/doc/man/fp2anim.1.mml =================================================================== --- tags/1.2.3/doc/man/fp2anim.1.mml (nonexistent) +++ tags/1.2.3/doc/man/fp2anim.1.mml (revision 8969) @@ -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.3/doc/man/gsch2pcb-rnd.1 =================================================================== --- tags/1.2.3/doc/man/gsch2pcb-rnd.1 (nonexistent) +++ tags/1.2.3/doc/man/gsch2pcb-rnd.1 (revision 8969) @@ -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.3/doc/man/index.html =================================================================== --- tags/1.2.3/doc/man/index.html (nonexistent) +++ tags/1.2.3/doc/man/index.html (revision 8969) @@ -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.3/doc/man/pcb-prj2lht.1 =================================================================== --- tags/1.2.3/doc/man/pcb-prj2lht.1 (nonexistent) +++ tags/1.2.3/doc/man/pcb-prj2lht.1 (revision 8969) @@ -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.3/doc/man/pcb-prj2lht.1.html =================================================================== --- tags/1.2.3/doc/man/pcb-prj2lht.1.html (nonexistent) +++ tags/1.2.3/doc/man/pcb-prj2lht.1.html (revision 8969) @@ -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.3/doc/man/pcb-prj2lht.1.mml =================================================================== --- tags/1.2.3/doc/man/pcb-prj2lht.1.mml (nonexistent) +++ tags/1.2.3/doc/man/pcb-prj2lht.1.mml (revision 8969) @@ -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.3/doc/man/pcb-rnd.1 =================================================================== --- tags/1.2.3/doc/man/pcb-rnd.1 (nonexistent) +++ tags/1.2.3/doc/man/pcb-rnd.1 (revision 8969) @@ -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.3/doc/man/pcb-rnd.1.html =================================================================== --- tags/1.2.3/doc/man/pcb-rnd.1.html (nonexistent) +++ tags/1.2.3/doc/man/pcb-rnd.1.html (revision 8969) @@ -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.3/doc/man/pcb-rnd.1.mml =================================================================== --- tags/1.2.3/doc/man/pcb-rnd.1.mml (nonexistent) +++ tags/1.2.3/doc/man/pcb-rnd.1.mml (revision 8969) @@ -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.3/doc/man/pcb-strip.1 =================================================================== --- tags/1.2.3/doc/man/pcb-strip.1 (nonexistent) +++ tags/1.2.3/doc/man/pcb-strip.1 (revision 8969) @@ -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.3/doc/man/pcb-strip.1.html =================================================================== --- tags/1.2.3/doc/man/pcb-strip.1.html (nonexistent) +++ tags/1.2.3/doc/man/pcb-strip.1.html (revision 8969) @@ -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.3/doc/man/pcb-strip.1.mml =================================================================== --- tags/1.2.3/doc/man/pcb-strip.1.mml (nonexistent) +++ tags/1.2.3/doc/man/pcb-strip.1.mml (revision 8969) @@ -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.3/doc/motivation.html =================================================================== --- tags/1.2.3/doc/motivation.html (nonexistent) +++ tags/1.2.3/doc/motivation.html (revision 8969) @@ -0,0 +1,111 @@ + + + + pcb-rnd - motivation + + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +

            pcb-rnd motivation

            +

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

            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 3: community requested features (from 2016 onward)

            +Overlapping phase 2 there is an ongoing + 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. + + Index: tags/1.2.3/doc/myfeature.html =================================================================== --- tags/1.2.3/doc/myfeature.html (nonexistent) +++ tags/1.2.3/doc/myfeature.html (revision 8969) @@ -0,0 +1,72 @@ + + + + pcb-rnd - my feature + + + + + + + + + + +
            Main + News + Doc + 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. To do so, 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%. +

            +However, this is a last resort solution, the above ones are clearly preferred. + + +

            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. The poll is there, 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.3/doc/news.html =================================================================== --- tags/1.2.3/doc/news.html (nonexistent) +++ tags/1.2.3/doc/news.html (revision 8969) @@ -0,0 +1,114 @@ + + + + pcb-rnd - news + + + + + + + + + + +
            Main + News + Doc + People + Events & timeline + pcb-rnd [pcb-rnd logo] +
            + + +
            + +

            News

            + +
            + + + + + + + + + + +
            + 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.3/doc/plan.txt =================================================================== --- tags/1.2.3/doc/plan.txt (nonexistent) +++ tags/1.2.3/doc/plan.txt (revision 8969) @@ -0,0 +1,76 @@ +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. 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) + 5. invocation + TODO + 6. feature plugins + autoplace + autoroute + ... (TODO) + 7. io plugins + lihata + kicadl + kicad s expr + 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.3/doc/resources/logo.pcb =================================================================== --- tags/1.2.3/doc/resources/logo.pcb (nonexistent) +++ tags/1.2.3/doc/resources/logo.pcb (revision 8969) @@ -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.3/doc/resources/logo128.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/logo128.png =================================================================== --- tags/1.2.3/doc/resources/logo128.png (nonexistent) +++ tags/1.2.3/doc/resources/logo128.png (revision 8969) Property changes on: tags/1.2.3/doc/resources/logo128.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/resources/logo16.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/logo16.png =================================================================== --- tags/1.2.3/doc/resources/logo16.png (nonexistent) +++ tags/1.2.3/doc/resources/logo16.png (revision 8969) Property changes on: tags/1.2.3/doc/resources/logo16.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/resources/logo256.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/logo256.png =================================================================== --- tags/1.2.3/doc/resources/logo256.png (nonexistent) +++ tags/1.2.3/doc/resources/logo256.png (revision 8969) Property changes on: tags/1.2.3/doc/resources/logo256.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/resources/logo32.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/logo32.png =================================================================== --- tags/1.2.3/doc/resources/logo32.png (nonexistent) +++ tags/1.2.3/doc/resources/logo32.png (revision 8969) Property changes on: tags/1.2.3/doc/resources/logo32.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/resources/logo32.xpm =================================================================== --- tags/1.2.3/doc/resources/logo32.xpm (nonexistent) +++ tags/1.2.3/doc/resources/logo32.xpm (revision 8969) @@ -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.3/doc/resources/logo64.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/logo64.png =================================================================== --- tags/1.2.3/doc/resources/logo64.png (nonexistent) +++ tags/1.2.3/doc/resources/logo64.png (revision 8969) Property changes on: tags/1.2.3/doc/resources/logo64.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/resources/logo64.xpm =================================================================== --- tags/1.2.3/doc/resources/logo64.xpm (nonexistent) +++ tags/1.2.3/doc/resources/logo64.xpm (revision 8969) @@ -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.3/doc/resources/logo_made_with.pcb =================================================================== --- tags/1.2.3/doc/resources/logo_made_with.pcb (nonexistent) +++ tags/1.2.3/doc/resources/logo_made_with.pcb (revision 8969) @@ -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.3/doc/resources/screenshot.jpg =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc/resources/screenshot.jpg =================================================================== --- tags/1.2.3/doc/resources/screenshot.jpg (nonexistent) +++ tags/1.2.3/doc/resources/screenshot.jpg (revision 8969) Property changes on: tags/1.2.3/doc/resources/screenshot.jpg ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc/tutorials/7805/7805.pcb =================================================================== --- tags/1.2.3/doc/tutorials/7805/7805.pcb (nonexistent) +++ tags/1.2.3/doc/tutorials/7805/7805.pcb (revision 8969) @@ -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.3/doc/tutorials/7805/7805.sch =================================================================== --- tags/1.2.3/doc/tutorials/7805/7805.sch (nonexistent) +++ tags/1.2.3/doc/tutorials/7805/7805.sch (revision 8969) @@ -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.3/doc/tutorials/7805/Info.lht =================================================================== --- tags/1.2.3/doc/tutorials/7805/Info.lht (nonexistent) +++ tags/1.2.3/doc/tutorials/7805/Info.lht (revision 8969) @@ -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.3/doc/tutorials/7805/Makefile =================================================================== --- tags/1.2.3/doc/tutorials/7805/Makefile (nonexistent) +++ tags/1.2.3/doc/tutorials/7805/Makefile (revision 8969) @@ -0,0 +1,5 @@ +7805.lht: 7805.sch + gsch2pcb-rnd -m import 7805.sch + +clean: + rm -f 7805.cmd Index: tags/1.2.3/doc/tutorials/7805/index.html =================================================================== --- tags/1.2.3/doc/tutorials/7805/index.html (nonexistent) +++ tags/1.2.3/doc/tutorials/7805/index.html (revision 8969) @@ -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.3/doc/user/01_intro/Makefile =================================================================== --- tags/1.2.3/doc/user/01_intro/Makefile (nonexistent) +++ tags/1.2.3/doc/user/01_intro/Makefile (revision 8969) @@ -0,0 +1,2 @@ +flow.svg: src/flow.dot + dot -Tsvg src/flow.dot > flow.svg Index: tags/1.2.3/doc/user/01_intro/flow.svg =================================================================== --- tags/1.2.3/doc/user/01_intro/flow.svg (nonexistent) +++ tags/1.2.3/doc/user/01_intro/flow.svg (revision 8969) @@ -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.3/doc/user/01_intro/history.html =================================================================== --- tags/1.2.3/doc/user/01_intro/history.html (nonexistent) +++ tags/1.2.3/doc/user/01_intro/history.html (revision 8969) @@ -0,0 +1,40 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd History

            +

            pcb-rnd is a rapid moving independent project that originated as a fork of the +Pcb codebase. + +

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

            In Fall 2013, Tibor Palinkas started an unofficial fork of Pcb to make and +share changes and improvements, and over the following years the fork was +officially announced, adopted additional users, and reached various milestones +

            
            +	15:39 < Igor2> $ svn log -r 1 svn://repo.hu/pcb-rnd
            +	15:39 < Igor2>
            +	------------------------------------------------------------------------
            +	15:39 < Igor2> r1 | igor2 | 2013-08-30 17:33:06 +0200 (Fri, 30 Aug 2013) | 2
            +	lines
            +	15:39 < Igor2> -Add: trunk
            +
            +

            +A more complete history can be found +in the pcb-history project. + + Index: tags/1.2.3/doc/user/01_intro/index.html =================================================================== --- tags/1.2.3/doc/user/01_intro/index.html (nonexistent) +++ tags/1.2.3/doc/user/01_intro/index.html (revision 8969) @@ -0,0 +1,41 @@ + + + + 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. Index: tags/1.2.3/doc/user/01_intro/src/flow.dot =================================================================== --- tags/1.2.3/doc/user/01_intro/src/flow.dot (nonexistent) +++ tags/1.2.3/doc/user/01_intro/src/flow.dot (revision 8969) @@ -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.3/doc/user/02_model/index.html =================================================================== --- tags/1.2.3/doc/user/02_model/index.html (nonexistent) +++ tags/1.2.3/doc/user/02_model/index.html (revision 8969) @@ -0,0 +1,431 @@ + + + + pcb-rnd user manual + + + + +

            pcb-rnd - user manual

            + +

            2. Model of the world

            +

            +Pcb-rnd is designed to handle 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". +

            +Font, which is always embedded in the design file 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

            +

            +Unlike a physical layer, a pcb-rnd layer has no thickness. It is a +2 dimensional, logical canvas, similar to layers in image manipulation software +like gimp. There are explicit and virtual 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 layer has no such flexibility: pcb-rnd computes +its content from explicit layers and there's no way to change the result +directly. A layer is always part of a layer group. + +

            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, [TODO]), 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 laeyr 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. +

                + +
                  top bottom intern global composite +
                copper yes yes yes no no +
                silk yes yes no no TODO +
                outline no no no yes no +
                mask yes yes no no yes +
                paste yes yes no no yes +
                + +

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

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

                +Extra 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 it's center, radius, start and end +angles, the user interface may offer drawing arcs by endpoints. +

                +Extra 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, it's 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 behaviour 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! +

                +Extra 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 a galvanized hole that connects copper rings on multiple layers. +Pcb-rnd currently has two limitations: there are no blind or buried vias - +a hole always punches all layers; there's no pad stack support, the copper +ring around the hole on each layer have the same sizes. +

                +A copper ring also has a per layer property whether or how it connects to +the surrounding polygon on the given layer; this is called the thermal style +of the via. The following options are available: + +
                thermal style appearance +
                no connection TODO +
                solid TODO +
                round x 90 TODO +
                round x 45 TODO +
                sharp x 90 TODO +
                sharp x 45 TODO +
                +

                +The shape of the copper annulus (the ring) is also selectable from a predefined +set of symmetrical and asymmetrical set: + +
                shape appearance +
                ring (default) TODO +
                square TODO +
                octagon TODO +
                asymmetrical TODO +
                + +

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

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

                + +
                name description +
                name pin name, e.g. "base" +
                number pin name, e.g. 2 +
                intconn internal element connections (see section TODO) +
                + +Extra 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") +
                + +

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

                + +
                name description +
                name pin name, e.g. "base" +
                number pin name, e.g. 2 +
                intconn internal element connections (see section TODO) +
                + +Extra 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. rat line objects

                +

                +A rat line represents a logical connection that is not yet realized in copper. +It connects two drawing primitives. + +

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

                +

                + +
                physical board term pcb-rnd term +
                layer layer group +
                copper layer layer group with copper layers +
                substrate N/A +
                contour of the board outline layer +
                outline routing path outline layer +
                polygon pour polygon +
                plane polygon +
                Index: tags/1.2.3/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.3/doc/user/02_model/obj_arc.png =================================================================== --- tags/1.2.3/doc/user/02_model/obj_arc.png (nonexistent) +++ tags/1.2.3/doc/user/02_model/obj_arc.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/02_model/obj_line.png =================================================================== --- tags/1.2.3/doc/user/02_model/obj_line.png (nonexistent) +++ tags/1.2.3/doc/user/02_model/obj_line.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/02_model/objects_basic.png =================================================================== --- tags/1.2.3/doc/user/02_model/objects_basic.png (nonexistent) +++ tags/1.2.3/doc/user/02_model/objects_basic.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/02_model/objects_complex.png =================================================================== --- tags/1.2.3/doc/user/02_model/objects_complex.png (nonexistent) +++ tags/1.2.3/doc/user/02_model/objects_complex.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/02_model/src/Makefile =================================================================== --- tags/1.2.3/doc/user/02_model/src/Makefile (nonexistent) +++ tags/1.2.3/doc/user/02_model/src/Makefile (revision 8969) @@ -0,0 +1,24 @@ +PCBRND=pcb-rnd +CLEANFILES= ../*.png + +all: ../objects_basic.png ../objects_complex.png ../obj_line.png \ + ../obj_arc.png + +../objects_basic.png: objects_basic.lht + $(PCBRND) -x png --dpi 450 objects_basic.lht + mv objects_basic.lht.png ../objects_basic.png + +../objects_complex.png: objects_complex.lht + $(PCBRND) -x png --dpi 450 objects_complex.lht + mv objects_complex.lht.png ../objects_complex.png + +../obj_line.png: obj_line.lht + $(PCBRND) -x png --dpi 450 obj_line.lht + mv obj_line.lht.png ../obj_line.png + +../obj_arc.png: obj_arc.lht + $(PCBRND) -x png --dpi 450 obj_arc.lht + mv obj_arc.lht.png ../obj_arc.png + +clean: $(CLEANRULES) + -rm $(CLEANFILES) Index: tags/1.2.3/doc/user/02_model/src/obj_arc.lht =================================================================== --- tags/1.2.3/doc/user/02_model/src/obj_arc.lht (nonexistent) +++ tags/1.2.3/doc/user/02_model/src/obj_arc.lht (revision 8969) @@ -0,0 +1,2424 @@ +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:font { + ha:geda_pcb { + cell_width=1.270001mm; cell_height=1.651001mm; + ha:symbols { + ha:] { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&5c { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:b { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:c { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:e { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=40.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:f { + width=0.381001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:g { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:h { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:i { + width=0.001um; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:j { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=65.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:k { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:l { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:m { + width=0.889001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=25.0mil; y1=30.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=30.0mil; y1=30.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=35.0mil; y1=35.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:n { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:o { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:p { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:r { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:s { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:t { + width=0.254001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:u { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:v { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:w { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=30.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:x { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:z { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:~ { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&7b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&7d { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:| { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&20 { + width=0.0; delta=18.0mil; + li:objects { + } + height = 0.0 + } + ha:&23 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:&26 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:! { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:" { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:$ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=20.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=45.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=40.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:% { + width=1.016001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=25.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=50.0mil; x2=40.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=35.0mil; y1=50.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=40.0mil; y1=40.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=35.0mil; x2=40.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=25.0mil; y1=40.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=25.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=25.0mil; y1=45.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=30.0mil; y1=50.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:' { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:( { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:) { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:* { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:+ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:, { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=60.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.524001mm + } + ha:- { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.762001mm + } + ha:. { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:0 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:1 { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=18.0mil; x2=8.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=8.0mil; y1=10.0mil; x2=8.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:2 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:3 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=23.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:4 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:5 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=25.0mil; x2=15.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=25.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:6 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=28.0mil; x2=20.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:7 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:8 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=37.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=37.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=7.0mil; y1=30.0mil; x2=13.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=37.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=37.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=23.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=15.0mil; x2=0.0; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:9 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:< { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:> { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:? { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:@ { + width=1.270001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=40.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=50.0mil; y1=35.0mil; x2=50.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=50.0mil; y1=10.0mil; x2=40.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=40.0mil; y1=0.0; x2=10.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=10.0mil; y1=0.0; x2=0.0; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=35.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=30.0mil; x2=40.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=35.0mil; y1=30.0mil; x2=35.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=35.0mil; y1=20.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=20.0mil; y1=15.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=20.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=40.0mil; y1=35.0mil; x2=50.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:A { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=20.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=7.0mil; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=20.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:B { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=33.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=28.0mil; x2=20.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:C { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=43.0mil; x2=7.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=17.0mil; x2=0.0; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=17.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=7.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:D { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=17.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=17.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=50.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=18.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:E { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:F { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:G { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:H { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:I { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:J { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=10.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:K { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:L { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:M { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=30.0mil; y1=10.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&2f { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:&3a { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&3b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&3d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:O { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:P { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:N { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:R { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=13.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:S { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:U { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:V { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:T { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:X { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:W { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:[ { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:^ { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.381001mm + } + ha:Z { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:a { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=45.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:_ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + } + } + } +ha:netlists { + + li:input { + } +} +} Index: tags/1.2.3/doc/user/02_model/src/obj_line.lht =================================================================== --- tags/1.2.3/doc/user/02_model/src/obj_line.lht (nonexistent) +++ tags/1.2.3/doc/user/02_model/src/obj_line.lht (revision 8969) @@ -0,0 +1,2342 @@ +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:font { + ha:geda_pcb { + cell_width=1.270001mm; cell_height=1.651001mm; + ha:symbols { + ha:] { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&5c { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:b { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:c { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:e { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=40.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:f { + width=0.381001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:g { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:h { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:i { + width=0.001um; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:j { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=65.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:k { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:l { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:m { + width=0.889001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=25.0mil; y1=30.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=30.0mil; y1=30.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=35.0mil; y1=35.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:n { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:o { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:p { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:r { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:s { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:t { + width=0.254001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:u { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:v { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:w { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=30.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:x { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:z { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:~ { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&7b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&7d { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:| { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&20 { + width=0.0; delta=18.0mil; + li:objects { + } + height = 0.0 + } + ha:&23 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:&26 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:! { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:" { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:$ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=20.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=45.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=40.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:% { + width=1.016001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=25.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=50.0mil; x2=40.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=35.0mil; y1=50.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=40.0mil; y1=40.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=35.0mil; x2=40.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=25.0mil; y1=40.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=25.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=25.0mil; y1=45.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=30.0mil; y1=50.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:' { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:( { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:) { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:* { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:+ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:, { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=60.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.524001mm + } + ha:- { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.762001mm + } + ha:. { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:0 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:1 { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=18.0mil; x2=8.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=8.0mil; y1=10.0mil; x2=8.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:2 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:3 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=23.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:4 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:5 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=25.0mil; x2=15.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=25.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:6 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=28.0mil; x2=20.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:7 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:8 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=37.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=37.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=7.0mil; y1=30.0mil; x2=13.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=37.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=37.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=23.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=15.0mil; x2=0.0; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:9 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:< { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:> { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:? { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:@ { + width=1.270001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=40.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=50.0mil; y1=35.0mil; x2=50.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=50.0mil; y1=10.0mil; x2=40.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=40.0mil; y1=0.0; x2=10.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=10.0mil; y1=0.0; x2=0.0; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=35.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=30.0mil; x2=40.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=35.0mil; y1=30.0mil; x2=35.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=35.0mil; y1=20.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=20.0mil; y1=15.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=20.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=40.0mil; y1=35.0mil; x2=50.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:A { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=20.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=7.0mil; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=20.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:B { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=33.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=28.0mil; x2=20.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:C { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=43.0mil; x2=7.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=17.0mil; x2=0.0; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=17.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=7.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:D { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=17.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=17.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=50.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=18.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:E { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:F { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:G { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:H { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:I { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:J { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=10.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:K { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:L { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:M { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=30.0mil; y1=10.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&2f { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:&3a { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&3b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&3d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:O { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:P { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:N { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:R { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=13.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:S { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:U { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:V { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:T { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:X { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:W { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:[ { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:^ { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.381001mm + } + ha:Z { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:a { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=45.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:_ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + } + } + } +ha:netlists { + + li:input { + } +} +} Index: tags/1.2.3/doc/user/02_model/src/objects_basic.lht =================================================================== --- tags/1.2.3/doc/user/02_model/src/objects_basic.lht (nonexistent) +++ tags/1.2.3/doc/user/02_model/src/objects_basic.lht (revision 8969) @@ -0,0 +1,2282 @@ +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:font { + ha:geda_pcb { + cell_width=1.270001mm; cell_height=1.651001mm; + ha:symbols { + ha:] { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&5c { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:b { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:c { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:e { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=40.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:f { + width=0.381001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:g { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:h { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:i { + width=0.001um; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:j { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=65.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:k { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:l { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:m { + width=0.889001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=25.0mil; y1=30.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=30.0mil; y1=30.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=35.0mil; y1=35.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:n { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:o { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:p { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:r { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:s { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:t { + width=0.254001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:u { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:v { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:w { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=30.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:x { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:z { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:~ { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&7b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&7d { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:| { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&20 { + width=0.0; delta=18.0mil; + li:objects { + } + height = 0.0 + } + ha:&23 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:&26 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:! { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:" { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:$ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=20.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=45.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=40.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:% { + width=1.016001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=25.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=50.0mil; x2=40.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=35.0mil; y1=50.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=40.0mil; y1=40.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=35.0mil; x2=40.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=25.0mil; y1=40.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=25.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=25.0mil; y1=45.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=30.0mil; y1=50.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:' { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:( { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:) { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:* { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:+ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:, { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=60.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.524001mm + } + ha:- { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.762001mm + } + ha:. { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:0 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:1 { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=18.0mil; x2=8.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=8.0mil; y1=10.0mil; x2=8.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:2 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:3 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=23.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:4 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:5 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=25.0mil; x2=15.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=25.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:6 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=28.0mil; x2=20.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:7 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:8 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=37.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=37.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=7.0mil; y1=30.0mil; x2=13.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=37.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=37.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=23.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=15.0mil; x2=0.0; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:9 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:< { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:> { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:? { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:@ { + width=1.270001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=40.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=50.0mil; y1=35.0mil; x2=50.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=50.0mil; y1=10.0mil; x2=40.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=40.0mil; y1=0.0; x2=10.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=10.0mil; y1=0.0; x2=0.0; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=35.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=30.0mil; x2=40.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=35.0mil; y1=30.0mil; x2=35.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=35.0mil; y1=20.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=20.0mil; y1=15.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=20.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=40.0mil; y1=35.0mil; x2=50.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:A { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=20.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=7.0mil; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=20.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:B { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=33.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=28.0mil; x2=20.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:C { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=43.0mil; x2=7.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=17.0mil; x2=0.0; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=17.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=7.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:D { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=17.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=17.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=50.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=18.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:E { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:F { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:G { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:H { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:I { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:J { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=10.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:K { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:L { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:M { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=30.0mil; y1=10.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&2f { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:&3a { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&3b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&3d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:O { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:P { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:N { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:R { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=13.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:S { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:U { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:V { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:T { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:X { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:W { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:[ { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:^ { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.381001mm + } + ha:Z { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:a { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=45.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:_ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + } + } + } +ha:netlists { + + li:input { + } +} +} Index: tags/1.2.3/doc/user/02_model/src/objects_complex.lht =================================================================== --- tags/1.2.3/doc/user/02_model/src/objects_complex.lht (nonexistent) +++ tags/1.2.3/doc/user/02_model/src/objects_complex.lht (revision 8969) @@ -0,0 +1,2223 @@ +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:font { + ha:geda_pcb { + cell_width=1.270001mm; cell_height=1.651001mm; + ha:symbols { + ha:] { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&5c { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:b { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:c { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:e { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=40.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:f { + width=0.381001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:g { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:h { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:i { + width=0.001um; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:j { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=21.0mil; thickness=10.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=65.0mil; x2=5.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:k { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:l { + width=0.127001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:m { + width=0.889001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=25.0mil; y1=30.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=30.0mil; y1=30.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=35.0mil; y1=35.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:n { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:o { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:p { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:r { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:s { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=40.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:t { + width=0.254001mm; delta=10.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:u { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:v { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:w { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=30.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:x { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=65.0mil; x2=20.0mil; y2=60.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=65.0mil; x2=15.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=60.0mil; x2=5.0mil; y2=65.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.651001mm + } + ha:z { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:~ { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=15.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=35.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&7b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=15.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&7d { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=35.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=35.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:| { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&20 { + width=0.0; delta=18.0mil; + li:objects { + } + height = 0.0 + } + ha:&23 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=20.0mil; x2=5.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:&26 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:! { + width=0.001um; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:" { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:$ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=20.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=35.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=45.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=45.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=40.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:% { + width=1.016001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=10.0mil; x2=15.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=25.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=25.0mil; x2=10.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=20.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=50.0mil; x2=40.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=35.0mil; y1=50.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=40.0mil; y1=40.0mil; x2=40.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=35.0mil; x2=40.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=25.0mil; y1=40.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=25.0mil; y1=40.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=25.0mil; y1=45.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=30.0mil; y1=50.0mil; x2=35.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:' { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.508001mm + } + ha:( { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:) { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=15.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:* { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:+ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=20.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:, { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=60.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.524001mm + } + ha:- { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.762001mm + } + ha:. { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:0 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=40.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:1 { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=18.0mil; x2=8.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=8.0mil; y1=10.0mil; x2=8.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:2 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:3 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=20.0mil; y1=23.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:4 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:5 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=25.0mil; x2=15.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=15.0mil; y1=25.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:6 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=28.0mil; x2=20.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=33.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:7 { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:8 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=37.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=37.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=7.0mil; y1=30.0mil; x2=13.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=37.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=37.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=0.0; y1=23.0mil; x2=7.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=0.0; y1=15.0mil; x2=0.0; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=13.0mil; y1=30.0mil; x2=20.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:9 { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:< { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:> { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.016001mm + } + ha:? { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=45.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=0.0; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:@ { + width=1.270001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=40.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=40.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=50.0mil; y1=35.0mil; x2=50.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=50.0mil; y1=10.0mil; x2=40.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=40.0mil; y1=0.0; x2=10.0mil; y2=0.0; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=10.0mil; y1=0.0; x2=0.0; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=15.0mil; y1=20.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=35.0mil; x2=30.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=30.0mil; y1=35.0mil; x2=35.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.11 { + x1=35.0mil; y1=30.0mil; x2=40.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.12 { + x1=35.0mil; y1=30.0mil; x2=35.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.13 { + x1=35.0mil; y1=20.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.14 { + x1=20.0mil; y1=15.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.15 { + x1=20.0mil; y1=15.0mil; x2=15.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.16 { + x1=40.0mil; y1=35.0mil; x2=50.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:A { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=20.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=20.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=7.0mil; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=20.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=20.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:B { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=33.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=33.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=28.0mil; x2=20.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=20.0mil; y1=28.0mil; x2=25.0mil; y2=23.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:C { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=43.0mil; x2=7.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=17.0mil; x2=0.0; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=17.0mil; x2=7.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=7.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:D { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=18.0mil; y1=10.0mil; x2=25.0mil; y2=17.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=17.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=18.0mil; y1=50.0mil; x2=25.0mil; y2=43.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=50.0mil; x2=18.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=10.0mil; x2=18.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:E { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:F { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=28.0mil; x2=15.0mil; y2=28.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:G { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:H { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=25.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:I { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:J { + width=0.381001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=7.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=15.0mil; y1=10.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=50.0mil; x2=15.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=0.0; y1=45.0mil; x2=0.0; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:K { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=30.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:L { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:M { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=15.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=30.0mil; y1=10.0mil; x2=30.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&2f { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=45.0mil; x2=30.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.143001mm + } + ha:&3a { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:&3b { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=10.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=25.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:&3d { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=25.0mil; x2=20.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=35.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.889001mm + } + ha:O { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:P { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:N { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:R { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=25.0mil; y1=15.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=10.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=13.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:S { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=20.0mil; y1=10.0mil; x2=25.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=15.0mil; x2=0.0; y2=25.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=25.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=5.0mil; y1=30.0mil; x2=20.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=30.0mil; x2=25.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=25.0mil; y1=35.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=20.0mil; y1=50.0mil; x2=25.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.9 { + x1=5.0mil; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.10 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Q { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=10.0mil; x2=15.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=10.0mil; x2=20.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=15.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=40.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=5.0mil; y1=50.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=10.0mil; y1=35.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:U { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=20.0mil; y1=10.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:V { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=50.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:T { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=10.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:X { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:Y { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=10.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=10.0mil; y1=30.0mil; x2=20.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=10.0mil; y1=30.0mil; x2=10.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:W { + width=0.762001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=0.0; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=30.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=15.0mil; y1=30.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=25.0mil; y1=50.0mil; x2=30.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=30.0mil; y1=30.0mil; x2=30.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:[ { + width=0.127001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=10.0mil; x2=0.0; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:^ { + width=0.254001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=15.0mil; x2=5.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=10.0mil; x2=10.0mil; y2=15.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 0.381001mm + } + ha:Z { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=10.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=10.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=50.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:a { + width=0.635001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=15.0mil; y1=30.0mil; x2=20.0mil; y2=35.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.1 { + x1=5.0mil; y1=30.0mil; x2=15.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.2 { + x1=0.0; y1=35.0mil; x2=5.0mil; y2=30.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.3 { + x1=0.0; y1=35.0mil; x2=0.0; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.4 { + x1=0.0; y1=45.0mil; x2=5.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.5 { + x1=20.0mil; y1=30.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.6 { + x1=20.0mil; y1=45.0mil; x2=25.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.7 { + x1=5.0mil; y1=50.0mil; x2=15.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + ha:line.8 { + x1=15.0mil; y1=50.0mil; x2=20.0mil; y2=45.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + ha:_ { + width=0.508001mm; delta=12.0mil; + li:objects { + ha:line.0 { + x1=0.0; y1=50.0mil; x2=20.0mil; y2=50.0mil; thickness=8.0mil; clearance=0.0; + } + } + height = 1.270001mm + } + } + } + } +ha:netlists { + + li:input { + } +} +} Index: tags/1.2.3/doc/user/04_invoc/index.html =================================================================== --- tags/1.2.3/doc/user/04_invoc/index.html (nonexistent) +++ tags/1.2.3/doc/user/04_invoc/index.html (revision 8969) @@ -0,0 +1,28 @@ + + + + pcb-rnd user manual + + + + +

                pcb-rnd - user manual

                + +

                5.1 User Invocation (aka running pcb-rnd)

                +

                +pcb-rnd is typically run by invoking it from the shell after installation +

                + +pcb-rnd [main options] + + +

                +At invocation, the user can learn about pcb-rnd +

                + +pcb-rnd --help + +

                +And at this time, choose alternative guis (Gtk, lesstif, remote) + + Index: tags/1.2.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_coordsreadout.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_layerops.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_main.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_main.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_main.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_menus.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_menus.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_opsreadout.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_routestyle.png (revision 8969) Property changes on: tags/1.2.3/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.3/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.3/doc/user/05_ui/01_gtk/base_window_highlight_workops.png =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/base_window_highlight_workops.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/05_ui/01_gtk/index.html =================================================================== --- tags/1.2.3/doc/user/05_ui/01_gtk/index.html (nonexistent) +++ tags/1.2.3/doc/user/05_ui/01_gtk/index.html (revision 8969) @@ -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.3/doc/user/05_ui/02_cli/index.html =================================================================== --- tags/1.2.3/doc/user/05_ui/02_cli/index.html (nonexistent) +++ tags/1.2.3/doc/user/05_ui/02_cli/index.html (revision 8969) @@ -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.3/doc/user/05_ui/index.html =================================================================== --- tags/1.2.3/doc/user/05_ui/index.html (nonexistent) +++ tags/1.2.3/doc/user/05_ui/index.html (revision 8969) @@ -0,0 +1,28 @@ + + + + pcb-rnd user manual + + + + +

                pcb-rnd - user manual

                + +

                4. User Interface (UI)

                +

                +pcb-rnd offers various user interface plugins. The plugins connect between +various input methods and the pcb-rnd core to offer different functionality +matching 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.3/doc/user/06_feature/djopt/Makefile =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/Makefile (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/Makefile (revision 8969) @@ -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.3/doc/user/06_feature/djopt/Post.html =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/Post.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/Post.html (revision 8969) @@ -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.3/doc/user/06_feature/djopt/Pre.html =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/Pre.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/Pre.html (revision 8969) @@ -0,0 +1,14 @@ + + +

Action djopt()

+ +The different types of optimizations change your board in order to +reduce the total trace length and via count. Each optimization is accessible +using an argument, e.g. djopt(miter). The basic actions have to be run multiple +times as each iteration will change the design making new changes possible for +subsequent iterations with the same or other actions. +

+Click on the images to download the example .pcb design. + + +
argument name description example in example out after 1st iteration Index: tags/1.2.3/doc/user/06_feature/djopt/debumpify.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/debumpify.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/debumpify.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/debumpify.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/debumpify.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/debumpify.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/debumpify.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/debumpify.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/debumpify.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/debumpify.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/debumpify.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/debumpify.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/debumpify.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/debumpify.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/debumpify.txt (revision 8969) @@ -0,0 +1,2 @@ +Looks for U-shaped traces (with 90 degree corners) that can be shortened +or eliminated. Index: tags/1.2.3/doc/user/06_feature/djopt/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/index.html (revision 8969) @@ -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.3/doc/user/06_feature/djopt/miter.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/miter.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/miter.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/miter.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/miter.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/miter.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/miter.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/miter.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/miter.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/miter.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/miter.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/miter.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/miter.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/miter.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/miter.txt (revision 8969) @@ -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.3/doc/user/06_feature/djopt/orthopull.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/orthopull.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/orthopull.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/orthopull.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/orthopull.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/orthopull.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/orthopull.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/orthopull.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/orthopull.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/orthopull.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/orthopull.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/orthopull.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/orthopull.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/orthopull.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/orthopull.txt (revision 8969) @@ -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.3/doc/user/06_feature/djopt/unjaggy.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/unjaggy.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/unjaggy.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/unjaggy.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/unjaggy.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/unjaggy.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/unjaggy.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/unjaggy.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/unjaggy.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/unjaggy.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/unjaggy.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/unjaggy.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/unjaggy.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/unjaggy.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/unjaggy.txt (revision 8969) @@ -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.3/doc/user/06_feature/djopt/vianudge.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/vianudge.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/vianudge.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/vianudge.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/vianudge.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/vianudge.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/vianudge.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/vianudge.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/vianudge.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/vianudge.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/vianudge.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/vianudge.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/vianudge.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/vianudge.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/vianudge.txt (revision 8969) @@ -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.3/doc/user/06_feature/djopt/viatrim.out.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/viatrim.out.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/viatrim.out.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/viatrim.out.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/viatrim.out.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/viatrim.out.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/viatrim.pcb =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/viatrim.pcb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/viatrim.pcb (revision 8969) @@ -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.3/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.3/doc/user/06_feature/djopt/viatrim.png =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/viatrim.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/viatrim.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/djopt/viatrim.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/djopt/viatrim.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/djopt/viatrim.txt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/Credits =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/Credits (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/Credits (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/History =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/History (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/History (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/Makefile =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/Makefile (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/Makefile (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/Porting =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/Porting (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/Porting (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/gpmi_flow.dot =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow.dot (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow.dot (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/gpmi_flow.png =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_exp.dot =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_exp.dot (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_exp.dot (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_exp.png =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_exp.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_exp.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_load.dot =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_load.dot (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_load.dot (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_load.png =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_load.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_load.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_menu.dot =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_menu.dot (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_menu.dot (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_menu.png =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_menu.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_menu.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_reg.dot =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_reg.dot (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_reg.dot (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/gpmi_flow_reg.png =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_reg.png (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_flow_reg.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc/user/06_feature/gpmi/gpmi_temp_inst.txt =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/gpmi_temp_inst.txt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/gpmi_temp_inst.txt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/Makefile =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/Makefile (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/Makefile (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/XREF =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/XREF (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/XREF (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/actions.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/actions.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/actions.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/actions_ref.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/actions_ref.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/actions_ref.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/dialogs.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/dialogs.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/dialogs.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/dialogs_ref.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/dialogs_ref.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/dialogs_ref.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/event_id.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/event_id.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/event_id.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/hid.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/hid.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/hid.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/hid_ref.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/hid_ref.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/hid_ref.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/layout.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/layout.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/layout.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/packages/layout_ref.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/packages/layout_ref.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/packages/layout_ref.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.desc (revision 8969) @@ -0,0 +1,2 @@ +Create a new action hello() that prints "Hello world!" in the message log. + Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ID.name (revision 8969) @@ -0,0 +1 @@ +hello world (text, log) Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.bash (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.lua (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.pl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.py (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.rb (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.scm (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.stt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/ex.tcl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.desc (revision 8969) @@ -0,0 +1,3 @@ +Create a new action hello() that prints "Hello world!" in a popup window. + + Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ID.name (revision 8969) @@ -0,0 +1 @@ +hello world (popup window) Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.bash (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.lua (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.pl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.py (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.rb (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.scm (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.stt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/ex.tcl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/10_hello_gui/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.desc (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ID.name (revision 8969) @@ -0,0 +1 @@ +hello world (popup window + submenu) Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.bash (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.lua (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.pl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.py (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.rb (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.scm (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.stt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/ex.tcl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/12_hello_menu/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.desc (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ID.name (revision 8969) @@ -0,0 +1 @@ +action: move selected objects Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.bash (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.lua (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.pl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.py =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.py (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.py (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.rb (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.scm (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.stt (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/ex.tcl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/30_move/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/30_move/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.desc (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ID.name (revision 8969) @@ -0,0 +1 @@ +drill list exporter Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.lua (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/ex.tcl (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/35_export_drill/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.desc (revision 8969) @@ -0,0 +1 @@ +Create and animate an analog clock on a dedicated UI layer. Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ID.name (revision 8969) @@ -0,0 +1 @@ +animated clock on a UI layer Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.awk (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/ex.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/90_clock/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/90_clock/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/Makefile =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/Makefile (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/Makefile (revision 8969) @@ -0,0 +1,4 @@ +all: FORCE + cd ../util && ./rosetta_genpages.sh + +FORCE: Index: tags/1.2.3/doc/user/06_feature/gpmi/rosetta/index.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/index.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/index.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/rosetta/index.templ.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/rosetta/index.templ.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/rosetta/index.templ.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/scripting_intro.html =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/scripting_intro.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/scripting_intro.html (revision 8969) @@ -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.3/doc/user/06_feature/gpmi/util/Makefile =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/util/Makefile (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/util/Makefile (revision 8969) @@ -0,0 +1 @@ +all: Index: tags/1.2.3/doc/user/06_feature/gpmi/util/rosetta_genpages.sh =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/util/rosetta_genpages.sh (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/util/rosetta_genpages.sh (revision 8969) @@ -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.3/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.3/doc/user/06_feature/gpmi/util/tags =================================================================== --- tags/1.2.3/doc/user/06_feature/gpmi/util/tags (nonexistent) +++ tags/1.2.3/doc/user/06_feature/gpmi/util/tags (revision 8969) @@ -0,0 +1,4 @@ +#!/bin/sh + +tr "\n" " " | sed "s@\(<[^/]\)@\n\1@g;s@\(]*>\)@\1\n@g" + Property changes on: tags/1.2.3/doc/user/06_feature/gpmi/util/tags ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc/user/06_feature/query/tutor_cli.html =================================================================== --- tags/1.2.3/doc/user/06_feature/query/tutor_cli.html (nonexistent) +++ tags/1.2.3/doc/user/06_feature/query/tutor_cli.html (revision 8969) @@ -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.3/doc/user/08_util/01_gsch2pcb-rnd.htm =================================================================== --- tags/1.2.3/doc/user/08_util/01_gsch2pcb-rnd.htm (nonexistent) +++ tags/1.2.3/doc/user/08_util/01_gsch2pcb-rnd.htm (revision 8969) @@ -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.3/doc/user/08_util/install_cgi.html =================================================================== --- tags/1.2.3/doc/user/08_util/install_cgi.html (nonexistent) +++ tags/1.2.3/doc/user/08_util/install_cgi.html (revision 8969) @@ -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.3/doc/user/default.css =================================================================== --- tags/1.2.3/doc/user/default.css (nonexistent) +++ tags/1.2.3/doc/user/default.css (revision 8969) @@ -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.3/doc/user/index.html =================================================================== --- tags/1.2.3/doc/user/index.html (nonexistent) +++ tags/1.2.3/doc/user/index.html (revision 8969) @@ -0,0 +1,24 @@ + + + + pcb-rnd user manual + + + + +

pcb-rnd - user manual

+ +

Table of Contents

+

+

+ Index: tags/1.2.3/doc/windows.txt =================================================================== --- tags/1.2.3/doc/windows.txt (nonexistent) +++ tags/1.2.3/doc/windows.txt (revision 8969) @@ -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.3/doc/wishlist.txt =================================================================== --- tags/1.2.3/doc/wishlist.txt (nonexistent) +++ tags/1.2.3/doc/wishlist.txt (revision 8969) @@ -0,0 +1,34 @@ +Active user wishes: + W1: cschem [Chris] + W2: (BLOCKED: lihata testing) proper primitives [Chris] + W3: (BLOCKED: lihata testing) more generic footprints [Chris, Evan] + W4: user doc [Miloh] + W5: (BLOCKED: lihata testing) 3d modeller export [Miloh, Evan] + W7: (BLOCKED: lihata testing) programmable drc (star grounding) [James] + W8: (BLOCKED: need resources) gl support [Erich, Evan] + W9: push & shove [Erich, Evan] + +User wishes fulfilled: + W6: GUI access to object attributes: gtk editor, find/select by attrib [James] + +Plan (parallel threads of development): + + A. file format and model + Steps: + 1. (done) lihata persistency + 2. (done) native lihata file format + 3. (done) extend the file format + - everything should have an attribute hash -> W6 + - footprints should have optional attachments (e.g. 3d models) -> W5 + This helps us testing out the persistent-lihata idea that'd be + later used in cschem from the start -> W1 + This is also needed for more generic footprint implementation -> W3 + + B. visible attribute support + Steps: + 1. (done) GTK dialog box for attribute edition + 2. (done) search & select should work by attribute + 3. (done) extend the routing style system to auto-add attributes + (this needs A., the new file format) + Allows the user to manage properties like "50 ohm net" in attributes, + to group objects by property, and to select them by property. -> W6 Index: tags/1.2.3/doc-orig/Makefile =================================================================== --- tags/1.2.3/doc-orig/Makefile (nonexistent) +++ tags/1.2.3/doc-orig/Makefile (revision 8969) @@ -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.3/doc-orig/README =================================================================== --- tags/1.2.3/doc-orig/README (nonexistent) +++ tags/1.2.3/doc-orig/README (revision 8969) @@ -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.3/doc-orig/README.w32 =================================================================== --- tags/1.2.3/doc-orig/README.w32 (nonexistent) +++ tags/1.2.3/doc-orig/README.w32 (revision 8969) @@ -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.3/doc-orig/actions.texi =================================================================== --- tags/1.2.3/doc-orig/actions.texi (nonexistent) +++ tags/1.2.3/doc-orig/actions.texi (revision 8969) @@ -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.3/doc-orig/eps2png =================================================================== --- tags/1.2.3/doc-orig/eps2png (nonexistent) +++ tags/1.2.3/doc-orig/eps2png (revision 8969) @@ -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.3/doc-orig/eps2png ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc-orig/extract-docs =================================================================== --- tags/1.2.3/doc-orig/extract-docs (nonexistent) +++ tags/1.2.3/doc-orig/extract-docs (revision 8969) @@ -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.3/doc-orig/extract-docs ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc-orig/gcode.pcb =================================================================== --- tags/1.2.3/doc-orig/gcode.pcb (nonexistent) +++ tags/1.2.3/doc-orig/gcode.pcb (revision 8969) @@ -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.3/doc-orig/gcode.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode.pdf =================================================================== --- tags/1.2.3/doc-orig/gcode.pdf (nonexistent) +++ tags/1.2.3/doc-orig/gcode.pdf (revision 8969) Property changes on: tags/1.2.3/doc-orig/gcode.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/gcode.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode.png =================================================================== --- tags/1.2.3/doc-orig/gcode.png (nonexistent) +++ tags/1.2.3/doc-orig/gcode.png (revision 8969) Property changes on: tags/1.2.3/doc-orig/gcode.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/gcode_control_img.eps =================================================================== --- tags/1.2.3/doc-orig/gcode_control_img.eps (nonexistent) +++ tags/1.2.3/doc-orig/gcode_control_img.eps (revision 8969) @@ -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.3/doc-orig/gcode_control_img.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode_control_img.pdf =================================================================== --- tags/1.2.3/doc-orig/gcode_control_img.pdf (nonexistent) +++ tags/1.2.3/doc-orig/gcode_control_img.pdf (revision 8969) Property changes on: tags/1.2.3/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.3/doc-orig/gcode_control_img.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode_control_img.png =================================================================== --- tags/1.2.3/doc-orig/gcode_control_img.png (nonexistent) +++ tags/1.2.3/doc-orig/gcode_control_img.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc-orig/gcode_tool_path.eps =================================================================== --- tags/1.2.3/doc-orig/gcode_tool_path.eps (nonexistent) +++ tags/1.2.3/doc-orig/gcode_tool_path.eps (revision 8969) @@ -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.3/doc-orig/gcode_tool_path.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode_tool_path.pdf =================================================================== --- tags/1.2.3/doc-orig/gcode_tool_path.pdf (nonexistent) +++ tags/1.2.3/doc-orig/gcode_tool_path.pdf (revision 8969) Property changes on: tags/1.2.3/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.3/doc-orig/gcode_tool_path.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/gcode_tool_path.png =================================================================== --- tags/1.2.3/doc-orig/gcode_tool_path.png (nonexistent) +++ tags/1.2.3/doc-orig/gcode_tool_path.png (revision 8969) Property changes on: tags/1.2.3/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.3/doc-orig/new_gen/Makefile =================================================================== --- tags/1.2.3/doc-orig/new_gen/Makefile (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/Makefile (revision 8969) @@ -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.3/doc-orig/new_gen/README =================================================================== --- tags/1.2.3/doc-orig/new_gen/README (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/README (revision 8969) @@ -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.3/doc-orig/new_gen/fractional_size.tab =================================================================== --- tags/1.2.3/doc-orig/new_gen/fractional_size.tab (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/fractional_size.tab (revision 8969) @@ -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.3/doc-orig/new_gen/letter_size.tab =================================================================== --- tags/1.2.3/doc-orig/new_gen/letter_size.tab (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/letter_size.tab (revision 8969) @@ -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.3/doc-orig/new_gen/metric_size.tab =================================================================== --- tags/1.2.3/doc-orig/new_gen/metric_size.tab (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/metric_size.tab (revision 8969) @@ -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.3/doc-orig/new_gen/tab2html.sh =================================================================== --- tags/1.2.3/doc-orig/new_gen/tab2html.sh (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/tab2html.sh (revision 8969) @@ -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.3/doc-orig/new_gen/tab2html.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/doc-orig/new_gen/wire_size.tab =================================================================== --- tags/1.2.3/doc-orig/new_gen/wire_size.tab (nonexistent) +++ tags/1.2.3/doc-orig/new_gen/wire_size.tab (revision 8969) @@ -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.3/doc-orig/options.texi =================================================================== --- tags/1.2.3/doc-orig/options.texi (nonexistent) +++ tags/1.2.3/doc-orig/options.texi (revision 8969) @@ -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.3/doc-orig/pad.pcb =================================================================== --- tags/1.2.3/doc-orig/pad.pcb (nonexistent) +++ tags/1.2.3/doc-orig/pad.pcb (revision 8969) @@ -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.3/doc-orig/pad.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/pad.pdf =================================================================== --- tags/1.2.3/doc-orig/pad.pdf (nonexistent) +++ tags/1.2.3/doc-orig/pad.pdf (revision 8969) Property changes on: tags/1.2.3/doc-orig/pad.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/pad.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/pad.png =================================================================== --- tags/1.2.3/doc-orig/pad.png (nonexistent) +++ tags/1.2.3/doc-orig/pad.png (revision 8969) Property changes on: tags/1.2.3/doc-orig/pad.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/pcb.1 =================================================================== --- tags/1.2.3/doc-orig/pcb.1 (nonexistent) +++ tags/1.2.3/doc-orig/pcb.1 (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/doc-orig/pcb.css =================================================================== --- tags/1.2.3/doc-orig/pcb.css (nonexistent) +++ tags/1.2.3/doc-orig/pcb.css (revision 8969) @@ -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.3/doc-orig/pcb.html =================================================================== --- tags/1.2.3/doc-orig/pcb.html (nonexistent) +++ tags/1.2.3/doc-orig/pcb.html (revision 8969) @@ -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.3/doc-orig/pcbfile.texi =================================================================== --- tags/1.2.3/doc-orig/pcbfile.texi (nonexistent) +++ tags/1.2.3/doc-orig/pcbfile.texi (revision 8969) @@ -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.3/doc-orig/puller.pcb =================================================================== --- tags/1.2.3/doc-orig/puller.pcb (nonexistent) +++ tags/1.2.3/doc-orig/puller.pcb (revision 8969) @@ -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.3/doc-orig/puller.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/puller.pdf =================================================================== --- tags/1.2.3/doc-orig/puller.pdf (nonexistent) +++ tags/1.2.3/doc-orig/puller.pdf (revision 8969) Property changes on: tags/1.2.3/doc-orig/puller.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/puller.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/puller.png =================================================================== --- tags/1.2.3/doc-orig/puller.png (nonexistent) +++ tags/1.2.3/doc-orig/puller.png (revision 8969) Property changes on: tags/1.2.3/doc-orig/puller.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/refcard.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/refcard.pdf =================================================================== --- tags/1.2.3/doc-orig/refcard.pdf (nonexistent) +++ tags/1.2.3/doc-orig/refcard.pdf (revision 8969) Property changes on: tags/1.2.3/doc-orig/refcard.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/refcard.tex =================================================================== --- tags/1.2.3/doc-orig/refcard.tex (nonexistent) +++ tags/1.2.3/doc-orig/refcard.tex (revision 8969) @@ -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., 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 + + +\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.3/doc-orig/thermal.pcb =================================================================== --- tags/1.2.3/doc-orig/thermal.pcb (nonexistent) +++ tags/1.2.3/doc-orig/thermal.pcb (revision 8969) @@ -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.3/doc-orig/thermal.pdf =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/thermal.pdf =================================================================== --- tags/1.2.3/doc-orig/thermal.pdf (nonexistent) +++ tags/1.2.3/doc-orig/thermal.pdf (revision 8969) Property changes on: tags/1.2.3/doc-orig/thermal.pdf ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/thermal.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: tags/1.2.3/doc-orig/thermal.png =================================================================== --- tags/1.2.3/doc-orig/thermal.png (nonexistent) +++ tags/1.2.3/doc-orig/thermal.png (revision 8969) Property changes on: tags/1.2.3/doc-orig/thermal.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: tags/1.2.3/doc-orig/tutorial/Makefile =================================================================== --- tags/1.2.3/doc-orig/tutorial/Makefile (nonexistent) +++ tags/1.2.3/doc-orig/tutorial/Makefile (revision 8969) @@ -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.3/doc-orig/tutorial/tut1.pcb =================================================================== --- tags/1.2.3/doc-orig/tutorial/tut1.pcb (nonexistent) +++ tags/1.2.3/doc-orig/tutorial/tut1.pcb (revision 8969) @@ -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.3/font/HersheySans1.pcb_font =================================================================== --- tags/1.2.3/font/HersheySans1.pcb_font (nonexistent) +++ tags/1.2.3/font/HersheySans1.pcb_font (revision 8969) @@ -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.3/font/default_arc.lht =================================================================== --- tags/1.2.3/font/default_arc.lht (nonexistent) +++ tags/1.2.3/font/default_arc.lht (revision 8969) @@ -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.3/font/osifontASCII.lht =================================================================== --- tags/1.2.3/font/osifontASCII.lht (nonexistent) +++ tags/1.2.3/font/osifontASCII.lht (revision 8969) @@ -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.3/pcblib/Makefile =================================================================== --- tags/1.2.3/pcblib/Makefile (nonexistent) +++ tags/1.2.3/pcblib/Makefile (revision 8969) @@ -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.3/pcblib/README =================================================================== --- tags/1.2.3/pcblib/README (nonexistent) +++ tags/1.2.3/pcblib/README (revision 8969) @@ -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.3/pcblib/connector/BNC_LAY.fp =================================================================== --- tags/1.2.3/pcblib/connector/BNC_LAY.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/BNC_LAY.fp (revision 8969) @@ -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.3/pcblib/connector/DB15F.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB15F.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB15F.fp (revision 8969) @@ -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.3/pcblib/connector/DB15M.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB15M.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB15M.fp (revision 8969) @@ -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.3/pcblib/connector/DB25F.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB25F.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB25F.fp (revision 8969) @@ -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.3/pcblib/connector/DB25M.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB25M.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB25M.fp (revision 8969) @@ -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.3/pcblib/connector/DB37F.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB37F.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB37F.fp (revision 8969) @@ -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.3/pcblib/connector/DB37M.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB37M.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB37M.fp (revision 8969) @@ -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.3/pcblib/connector/DB9F.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB9F.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB9F.fp (revision 8969) @@ -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.3/pcblib/connector/DB9M.fp =================================================================== --- tags/1.2.3/pcblib/connector/DB9M.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/DB9M.fp (revision 8969) @@ -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.3/pcblib/connector/pwrjack.fp =================================================================== --- tags/1.2.3/pcblib/connector/pwrjack.fp (nonexistent) +++ tags/1.2.3/pcblib/connector/pwrjack.fp (revision 8969) @@ -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.3/pcblib/parametric/acy =================================================================== --- tags/1.2.3/pcblib/parametric/acy (nonexistent) +++ tags/1.2.3/pcblib/parametric/acy (revision 8969) @@ -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.3/pcblib/parametric/acy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/acy.awk =================================================================== --- tags/1.2.3/pcblib/parametric/acy.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/acy.awk (revision 8969) @@ -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.3/pcblib/parametric/alf =================================================================== --- tags/1.2.3/pcblib/parametric/alf (nonexistent) +++ tags/1.2.3/pcblib/parametric/alf (revision 8969) @@ -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.3/pcblib/parametric/alf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/alf.awk =================================================================== --- tags/1.2.3/pcblib/parametric/alf.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/alf.awk (revision 8969) @@ -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.3/pcblib/parametric/bga =================================================================== --- tags/1.2.3/pcblib/parametric/bga (nonexistent) +++ tags/1.2.3/pcblib/parametric/bga (revision 8969) @@ -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.3/pcblib/parametric/bga ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/bga.awk =================================================================== --- tags/1.2.3/pcblib/parametric/bga.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/bga.awk (revision 8969) @@ -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.3/pcblib/parametric/common.awk =================================================================== --- tags/1.2.3/pcblib/parametric/common.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/common.awk (revision 8969) @@ -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.3/pcblib/parametric/connector =================================================================== --- tags/1.2.3/pcblib/parametric/connector (nonexistent) +++ tags/1.2.3/pcblib/parametric/connector (revision 8969) @@ -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.3/pcblib/parametric/connector ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/connector.awk =================================================================== --- tags/1.2.3/pcblib/parametric/connector.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/connector.awk (revision 8969) @@ -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.3/pcblib/parametric/dip =================================================================== --- tags/1.2.3/pcblib/parametric/dip (nonexistent) +++ tags/1.2.3/pcblib/parametric/dip (revision 8969) @@ -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.3/pcblib/parametric/dip ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/dip.awk =================================================================== --- tags/1.2.3/pcblib/parametric/dip.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/dip.awk (revision 8969) @@ -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.3/pcblib/parametric/msop =================================================================== --- tags/1.2.3/pcblib/parametric/msop (nonexistent) +++ tags/1.2.3/pcblib/parametric/msop (revision 8969) @@ -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.3/pcblib/parametric/msop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/plcc =================================================================== --- tags/1.2.3/pcblib/parametric/plcc (nonexistent) +++ tags/1.2.3/pcblib/parametric/plcc (revision 8969) @@ -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.3/pcblib/parametric/plcc ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/plcc.awk =================================================================== --- tags/1.2.3/pcblib/parametric/plcc.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/plcc.awk (revision 8969) @@ -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.3/pcblib/parametric/qf =================================================================== --- tags/1.2.3/pcblib/parametric/qf (nonexistent) +++ tags/1.2.3/pcblib/parametric/qf (revision 8969) @@ -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.3/pcblib/parametric/qf ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/qf.awk =================================================================== --- tags/1.2.3/pcblib/parametric/qf.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/qf.awk (revision 8969) @@ -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.3/pcblib/parametric/qfn =================================================================== --- tags/1.2.3/pcblib/parametric/qfn (nonexistent) +++ tags/1.2.3/pcblib/parametric/qfn (revision 8969) @@ -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.3/pcblib/parametric/qfn ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/qfn.awk =================================================================== --- tags/1.2.3/pcblib/parametric/qfn.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/qfn.awk (revision 8969) @@ -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.3/pcblib/parametric/qfp =================================================================== --- tags/1.2.3/pcblib/parametric/qfp (nonexistent) +++ tags/1.2.3/pcblib/parametric/qfp (revision 8969) @@ -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.3/pcblib/parametric/qfp ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/qfp.awk =================================================================== --- tags/1.2.3/pcblib/parametric/qfp.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/qfp.awk (revision 8969) @@ -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.3/pcblib/parametric/qsop =================================================================== --- tags/1.2.3/pcblib/parametric/qsop (nonexistent) +++ tags/1.2.3/pcblib/parametric/qsop (revision 8969) @@ -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.3/pcblib/parametric/qsop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/rcy =================================================================== --- tags/1.2.3/pcblib/parametric/rcy (nonexistent) +++ tags/1.2.3/pcblib/parametric/rcy (revision 8969) @@ -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.3/pcblib/parametric/rcy ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/rcy.awk =================================================================== --- tags/1.2.3/pcblib/parametric/rcy.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/rcy.awk (revision 8969) @@ -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.3/pcblib/parametric/screw =================================================================== --- tags/1.2.3/pcblib/parametric/screw (nonexistent) +++ tags/1.2.3/pcblib/parametric/screw (revision 8969) @@ -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.3/pcblib/parametric/screw ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/screw.awk =================================================================== --- tags/1.2.3/pcblib/parametric/screw.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/screw.awk (revision 8969) @@ -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.3/pcblib/parametric/silkmark.help =================================================================== --- tags/1.2.3/pcblib/parametric/silkmark.help (nonexistent) +++ tags/1.2.3/pcblib/parametric/silkmark.help (revision 8969) @@ -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.3/pcblib/parametric/so =================================================================== --- tags/1.2.3/pcblib/parametric/so (nonexistent) +++ tags/1.2.3/pcblib/parametric/so (revision 8969) @@ -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.3/pcblib/parametric/so ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/so.awk =================================================================== --- tags/1.2.3/pcblib/parametric/so.awk (nonexistent) +++ tags/1.2.3/pcblib/parametric/so.awk (revision 8969) @@ -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.3/pcblib/parametric/ssop =================================================================== --- tags/1.2.3/pcblib/parametric/ssop (nonexistent) +++ tags/1.2.3/pcblib/parametric/ssop (revision 8969) @@ -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.3/pcblib/parametric/ssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/parametric/tssop =================================================================== --- tags/1.2.3/pcblib/parametric/tssop (nonexistent) +++ tags/1.2.3/pcblib/parametric/tssop (revision 8969) @@ -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.3/pcblib/parametric/tssop ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/pcblib/smd/01005.fp =================================================================== --- tags/1.2.3/pcblib/smd/01005.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/01005.fp (revision 8969) @@ -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.3/pcblib/smd/0201.fp =================================================================== --- tags/1.2.3/pcblib/smd/0201.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/0201.fp (revision 8969) @@ -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.3/pcblib/smd/0402.fp =================================================================== --- tags/1.2.3/pcblib/smd/0402.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/0402.fp (revision 8969) @@ -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.3/pcblib/smd/0603.fp =================================================================== --- tags/1.2.3/pcblib/smd/0603.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/0603.fp (revision 8969) @@ -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.3/pcblib/smd/0805.fp =================================================================== --- tags/1.2.3/pcblib/smd/0805.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/0805.fp (revision 8969) @@ -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.3/pcblib/smd/1008.fp =================================================================== --- tags/1.2.3/pcblib/smd/1008.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/1008.fp (revision 8969) @@ -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.3/pcblib/smd/1206.fp =================================================================== --- tags/1.2.3/pcblib/smd/1206.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/1206.fp (revision 8969) @@ -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.3/pcblib/smd/1210.fp =================================================================== --- tags/1.2.3/pcblib/smd/1210.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/1210.fp (revision 8969) @@ -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.3/pcblib/smd/1806.fp =================================================================== --- tags/1.2.3/pcblib/smd/1806.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/1806.fp (revision 8969) @@ -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.3/pcblib/smd/1825.fp =================================================================== --- tags/1.2.3/pcblib/smd/1825.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/1825.fp (revision 8969) @@ -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.3/pcblib/smd/2706.fp =================================================================== --- tags/1.2.3/pcblib/smd/2706.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/2706.fp (revision 8969) @@ -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.3/pcblib/smd/DO214.fp =================================================================== --- tags/1.2.3/pcblib/smd/DO214.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/DO214.fp (revision 8969) @@ -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.3/pcblib/smd/DO214AB.fp =================================================================== --- tags/1.2.3/pcblib/smd/DO214AB.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/DO214AB.fp (revision 8969) @@ -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.3/pcblib/smd/MPAK.fp =================================================================== --- tags/1.2.3/pcblib/smd/MPAK.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/MPAK.fp (revision 8969) @@ -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.3/pcblib/smd/SC70_3.fp =================================================================== --- tags/1.2.3/pcblib/smd/SC70_3.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SC70_3.fp (revision 8969) @@ -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.3/pcblib/smd/SC70_4.fp =================================================================== --- tags/1.2.3/pcblib/smd/SC70_4.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SC70_4.fp (revision 8969) @@ -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.3/pcblib/smd/SC90.fp =================================================================== --- tags/1.2.3/pcblib/smd/SC90.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SC90.fp (revision 8969) @@ -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.3/pcblib/smd/SOD106A.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD106A.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD106A.fp (revision 8969) @@ -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.3/pcblib/smd/SOD110.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD110.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD110.fp (revision 8969) @@ -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.3/pcblib/smd/SOD123.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD123.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD123.fp (revision 8969) @@ -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.3/pcblib/smd/SOD323.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD323.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD323.fp (revision 8969) @@ -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.3/pcblib/smd/SOD80.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD80.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD80.fp (revision 8969) @@ -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.3/pcblib/smd/SOD87.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOD87.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOD87.fp (revision 8969) @@ -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.3/pcblib/smd/SOT143.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT143.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT143.fp (revision 8969) @@ -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.3/pcblib/smd/SOT223.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT223.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT223.fp (revision 8969) @@ -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.3/pcblib/smd/SOT23.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT23.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT23.fp (revision 8969) @@ -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.3/pcblib/smd/SOT23D.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT23D.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT23D.fp (revision 8969) @@ -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.3/pcblib/smd/SOT25.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT25.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT25.fp (revision 8969) @@ -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.3/pcblib/smd/SOT26.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT26.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT26.fp (revision 8969) @@ -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.3/pcblib/smd/SOT323.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT323.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT323.fp (revision 8969) @@ -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.3/pcblib/smd/SOT323D.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT323D.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT323D.fp (revision 8969) @@ -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.3/pcblib/smd/SOT325.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT325.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT325.fp (revision 8969) @@ -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.3/pcblib/smd/SOT326.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT326.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT326.fp (revision 8969) @@ -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.3/pcblib/smd/SOT89.fp =================================================================== --- tags/1.2.3/pcblib/smd/SOT89.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/SOT89.fp (revision 8969) @@ -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.3/pcblib/smd/TANT_A.fp =================================================================== --- tags/1.2.3/pcblib/smd/TANT_A.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/TANT_A.fp (revision 8969) @@ -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.3/pcblib/smd/TANT_B.fp =================================================================== --- tags/1.2.3/pcblib/smd/TANT_B.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/TANT_B.fp (revision 8969) @@ -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.3/pcblib/smd/TANT_C.fp =================================================================== --- tags/1.2.3/pcblib/smd/TANT_C.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/TANT_C.fp (revision 8969) @@ -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.3/pcblib/smd/TANT_D.fp =================================================================== --- tags/1.2.3/pcblib/smd/TANT_D.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/TANT_D.fp (revision 8969) @@ -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.3/pcblib/smd/minimelf.fp =================================================================== --- tags/1.2.3/pcblib/smd/minimelf.fp (nonexistent) +++ tags/1.2.3/pcblib/smd/minimelf.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC49.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC49.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC49.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC49U.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC49U.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC49U.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC49UH.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC49UH.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC49UH.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC49U_3.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC49U_3.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC49U_3.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC49U_3H.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC49U_3H.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC49U_3H.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC51U.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC51U.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC51U.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HC51UH.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HC51UH.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HC51UH.fp (revision 8969) @@ -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.3/pcblib/tru-hole/HEPTAWATT.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/HEPTAWATT.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/HEPTAWATT.fp (revision 8969) @@ -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.3/pcblib/tru-hole/LED3.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/LED3.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/LED3.fp (revision 8969) @@ -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.3/pcblib/tru-hole/LED5.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/LED5.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/LED5.fp (revision 8969) @@ -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.3/pcblib/tru-hole/MULTIWATT11.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/MULTIWATT11.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/MULTIWATT11.fp (revision 8969) @@ -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.3/pcblib/tru-hole/MULTIWATT15.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/MULTIWATT15.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/MULTIWATT15.fp (revision 8969) @@ -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.3/pcblib/tru-hole/MULTIWATT8.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/MULTIWATT8.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/MULTIWATT8.fp (revision 8969) @@ -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.3/pcblib/tru-hole/OSC14.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/OSC14.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/OSC14.fp (revision 8969) @@ -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.3/pcblib/tru-hole/PENTAWATT.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/PENTAWATT.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/PENTAWATT.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TACT_6x6_4p =================================================================== --- tags/1.2.3/pcblib/tru-hole/TACT_6x6_4p (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TACT_6x6_4p (revision 8969) @@ -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.3/pcblib/tru-hole/TO126.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO126.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO126.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO126S.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO126S.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO126S.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO126SW.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO126SW.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO126SW.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO126W.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO126W.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO126W.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO18.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO18.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO18.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO218.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO218.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO218.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO220.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO220.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO220.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO220ACSTAND.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO220ACSTAND.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO220ACSTAND.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO220S.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO220S.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO220S.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO220SW.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO220SW.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO220SW.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO220W.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO220W.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO220W.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO247.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO247.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO247.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO247_2.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO247_2.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO247_2.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO251.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO251.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO251.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO264.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO264.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO264.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO39.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO39.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO39.fp (revision 8969) @@ -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.3/pcblib/tru-hole/TO92.fp =================================================================== --- tags/1.2.3/pcblib/tru-hole/TO92.fp (nonexistent) +++ tags/1.2.3/pcblib/tru-hole/TO92.fp (revision 8969) @@ -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.3/scconfig/Makefile =================================================================== --- tags/1.2.3/scconfig/Makefile (nonexistent) +++ tags/1.2.3/scconfig/Makefile (revision 8969) @@ -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.3/scconfig/README =================================================================== --- tags/1.2.3/scconfig/README (nonexistent) +++ tags/1.2.3/scconfig/README (revision 8969) @@ -0,0 +1,3 @@ +The configuration system that runs ./configure. + +The engine is scconfig. Index: tags/1.2.3/scconfig/Rev.h =================================================================== --- tags/1.2.3/scconfig/Rev.h (nonexistent) +++ tags/1.2.3/scconfig/Rev.h (revision 8969) @@ -0,0 +1 @@ +static const int myrev = 8920; Index: tags/1.2.3/scconfig/Rev.tab =================================================================== --- tags/1.2.3/scconfig/Rev.tab (nonexistent) +++ tags/1.2.3/scconfig/Rev.tab (revision 8969) @@ -0,0 +1,80 @@ +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.3/scconfig/cquote.c =================================================================== --- tags/1.2.3/scconfig/cquote.c (nonexistent) +++ tags/1.2.3/scconfig/cquote.c (revision 8969) @@ -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.3/scconfig/gen_conf.sh =================================================================== --- tags/1.2.3/scconfig/gen_conf.sh (nonexistent) +++ tags/1.2.3/scconfig/gen_conf.sh (revision 8969) @@ -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.3/scconfig/gen_conf.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/scconfig/gen_core_lists.sh =================================================================== --- tags/1.2.3/scconfig/gen_core_lists.sh (nonexistent) +++ tags/1.2.3/scconfig/gen_core_lists.sh (revision 8969) @@ -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.3/scconfig/gen_core_lists.sh ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: tags/1.2.3/scconfig/hooks.c =================================================================== --- tags/1.2.3/scconfig/hooks.c (nonexistent) +++ tags/1.2.3/scconfig/hooks.c (revision 8969) @@ -0,0 +1,868 @@ +#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.3" + +#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"); +} + +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); + +/* 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) { + if ((strcmp(value, sbuildin) == 0) || (strcmp(value, splugin) == 0) || (strcmp(value, sdisable) == 0)) { + all_plugin_select(value); + 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) +{ + char buff[1024]; + +#undef plugin_def +#undef plugin_header +#undef plugin_dep +#define plugin_def(name, desc, default_, all_) \ + if (all_) { \ + 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; + const char *host_ansi, *host_ped, *target_ansi, *target_ped; + + 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/math/rint/*", 0, 0); + require("libs/math/round/*", 0, 0); + require("libs/userpass/getpwuid/*", 0, 0); + + 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); + } + need_gtklibs = 1; + } + else { + report_repeat("WARNING: Since there's no libgtk2 found, disabling hid_gtk2*...\n"); + hook_custom_arg("Disable-hid_gtk2_gdk", NULL); + hook_custom_arg("Disable-hid_gtk2_gl", NULL); + } + } + + if (want_gtk3) { + if (istrue(get("libs/gui/cairo/presents"))) { + require("libs/gui/gtk3/presents", 0, 0); + if (!istrue(get("libs/gui/gtk3/presents"))) { + report_repeat("WARNING: Since there's no libgtk3 found, disabling hid_gtk3*...\n"); + hook_custom_arg("Disable-hid_gtk3_cairo", NULL); + } + else + need_gtklibs = 1; + } + else { + report_repeat("WARNING: not going to try gtk3 because cairo is not found\n"); + hook_custom_arg("Disable-hid_gtk3_cairo", NULL); + } + } + + 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 */ + if (plug_is_enabled("dbus")) { + require("libs/sul/dbus/presents", 0, 0); + if (!istrue(get("libs/sul/dbus/presents"))) { + report_repeat("WARNING: disabling the DBUS interface plugin because libdbus is not found or not configured...\n"); + hook_custom_arg("Disable-dbus", NULL); + } + } + + 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")); + + 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.3/scconfig/menucfg.c =================================================================== --- tags/1.2.3/scconfig/menucfg.c (nonexistent) +++ tags/1.2.3/scconfig/menucfg.c (revision 8969) @@ -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.3/scconfig/plugin_3state.h =================================================================== --- tags/1.2.3/scconfig/plugin_3state.h (nonexistent) +++ tags/1.2.3/scconfig/plugin_3state.h (revision 8969) @@ -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.3/scconfig/plugins.h =================================================================== --- tags/1.2.3/scconfig/plugins.h (nonexistent) +++ tags/1.2.3/scconfig/plugins.h (revision 8969) @@ -0,0 +1,130 @@ +/****************************************************************************** + 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_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_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("dbus", "DBUS interface", sdisable, 1) +plugin_def("diag", "diagnostic acts. for devs", 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("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("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("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_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_hyp", "hyperlynx .hyp loader", 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", sdisable, 0) +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", sdisable, 0) +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_eagle", "Eagle's xml format", sdisable, 0) +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("import_mentor_sch", "lib_gensexpr") +plugin_dep("export_lpr", "export_ps") +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_gtk2_gl", "draw_csect") +plugin_dep("hid_gtk2_gl", "draw_fontsel") +plugin_dep("io_kicad_legacy", "io_kicad") +plugin_dep("hid_lesstif", "draw_csect") +plugin_dep("hid_lesstif", "draw_fontsel") +plugin_dep("hid_lesstif", "lib_hid_common") +plugin_dep("io_kicad", "lib_gensexpr") +plugin_dep("io_eagle", "boardflip") +plugin_dep("lib_gtk_hid", "lib_hid_common") +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_gtk3_cairo", "draw_csect") +plugin_dep("hid_gtk3_cairo", "draw_fontsel") +plugin_dep("fp_wget", "fp_fs") +plugin_dep("export_xy", "export_bom") +plugin_dep("lib_gtk_common", "lib_gtk_config") +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_gdk", "draw_csect") +plugin_dep("hid_gtk2_gdk", "draw_fontsel") Index: tags/1.2.3/scconfig/revtest.c =================================================================== --- tags/1.2.3/scconfig/revtest.c (nonexistent) +++ tags/1.2.3/scconfig/revtest.c (revision 8969) @@ -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.3/scconfig/template/cdep.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/cdep.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/cdep.tmpasm (revision 8969) @@ -0,0 +1,59 @@ +# 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) +@] + +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.3/scconfig/template/comp_var.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/comp_var.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/comp_var.tmpasm (revision 8969) @@ -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.3/scconfig/template/compile.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/compile.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/compile.tmpasm (revision 8969) @@ -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.3/scconfig/template/debug.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/debug.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/debug.tmpasm (revision 8969) @@ -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.3/scconfig/template/plugin_conf.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/plugin_conf.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/plugin_conf.tmpasm (revision 8969) @@ -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.3/scconfig/template/plugin_sphash.tmpasm =================================================================== --- tags/1.2.3/scconfig/template/plugin_sphash.tmpasm (nonexistent) +++ tags/1.2.3/scconfig/template/plugin_sphash.tmpasm (revision 8969) @@ -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.3/scconfig =================================================================== --- tags/1.2.3/scconfig (nonexistent) +++ tags/1.2.3/scconfig (revision 8969) Property changes on: tags/1.2.3/scconfig ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## +svn://repo.hu/scconfig/trunk/src src Index: tags/1.2.3/src/Makefile.dep =================================================================== --- tags/1.2.3/src/Makefile.dep (nonexistent) +++ tags/1.2.3/src/Makefile.dep (revision 8969) @@ -0,0 +1,6242 @@ +### 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.h \ + move.h draw.h polygon.h rtree.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 vtptr.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 rtree.h rats.h netlist.h route_style.h remove.h \ + obj_pinvia_therm.h undo.h pcb-printf.h layer.h compat_nls.h vtptr.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.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/dbus/dbus-pcbmain.o: ../src_plugins/dbus/dbus-pcbmain.c \ + ../config.h ../src_plugins/dbus/dbus-pcbmain.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h +../src_plugins/dbus/dbus.o: ../src_plugins/dbus/dbus.c \ + ../src_plugins/dbus/dbus-pcbmain.h ../src_plugins/dbus/dbus-introspect.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 event.h \ + compat_misc.h hid.h compat_lrealpath.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 layer.h \ + ../src_plugins/diag/diag_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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h error.h dolists.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 remove.h move.h draw.h \ + undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h conf_core.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h rats.h \ + netlist.h route_style.h buffer.h change.h draw.h undo.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h polygon.h rtree.h compat_misc.h layer.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 math_helper.h macro.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h draw.h \ + hid_draw_helpers.h pcb-printf.h ../src_3rd/genvector/gds_char.h \ + compat_misc.h layer.h hid_attrib.h hid_flags.h hid_helper.h hid.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 obj_pinvia.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 rats.h netlist.h \ + route_style.h hid_helper.h layer.h compat_misc.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 hid.h hid_nogui.h hid_draw_helpers.h hid_init.h \ + hid_attrib.h hid_flags.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h obj_pinvia.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 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/scad.o: \ + ../src_plugins/export_openscad/scad.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h rats_patch.h board.h math_helper.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h error.h \ + buffer.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.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.h hid_draw_helpers.h hid_nogui.h \ + hid_init.h hid_attrib.h hid_helper.h \ + ../src_plugins/export_openscad/scad.h +../src_plugins/export_openscad/scadcomp.o: \ + ../src_plugins/export_openscad/scadcomp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h buffer.h \ + misc_util.h hid.h hid_nogui.h hid_draw_helpers.h hid_init.h \ + ../src_plugins/export_openscad/scad.h +../src_plugins/export_openscad/scadproto.o: \ + ../src_plugins/export_openscad/scadproto.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h buffer.h hid.h hid_nogui.h \ + hid_draw_helpers.h hid_init.h ../src_plugins/export_openscad/scad.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 layer.h pcb-printf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 hid.h hid_nogui.h hid_attrib.h hid_helper.h hid_init.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h flag.h layer.h \ + move.h remove.h rtree.h flag_str.h undo.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 rtree.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h conf_core.h compat_nls.h macro.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/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 \ + 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 +../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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/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 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 +../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 +../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h conf.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/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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_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 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/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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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_hid/gui.h \ + ../src_plugins/lib_gtk_common/ui_zoompan.h unit.h pcb_bool.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.h hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/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/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/hidgl.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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_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 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/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 \ + layer.h data.h crosshair.h vtonpoint.h route.h buffer.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 action_helper.h error.h \ + ../src_plugins/hid_gtk2_gl/hidgl.h rtree.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h conf.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/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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_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 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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 build_run.h crosshair.h layer.h \ + pcb-printf.h hid.h ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h \ + hid_cfg.h 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 buffer.h vtptr.h plug_footprint.h \ + vtlibrary.h hid.h ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 hid.h hid_nogui.h hid_draw_helpers.h hid_cfg.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.h hid_cfg.h \ + 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 error.h pcb-printf.h layer.h hid.h \ + hid_cfg.h hid_cfg_action.h hid_cfg.h hid_cfg_input.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 find.h rats.h netlist.h library.h route_style.h \ + vtroutestyle.h select.h operation.h undo.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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 pcb-printf.h hid.h \ + ../src_plugins/hid_lesstif/lesstif.h hid_cfg_input.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/server.o: ../src_plugins/hid_srv_ws/server.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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 polygon.h rtree.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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 +../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h netlist.h route_style.h rats_patch.h plug_io.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h compat_misc.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf.h ../src_plugins/import_mentor_sch/netlist_helper.h \ + ../src_3rd/liblihata/genht/htsp.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/liblihata/genht/hash.h \ + ../src_plugins/import_mentor_sch/netlist_helper.h \ + ../src_3rd/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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 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/liblihata/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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h compat_misc.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 rats_patch.h \ + compat_misc.h compat_nls.h paths.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h \ + change.h error.h undo.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_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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h compat_misc.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_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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h conf_core.h error.h \ + polygon.h rtree.h rtree.h hid_actions.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 search.h rats.h netlist.h route_style.h rotate.h compat_misc.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 ../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/liblihata/genht/htsi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/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 \ + ../src_plugins/io_kicad/read.h layer.h const.h netlist.h route_style.h \ + polygon.h rtree.h misc_util.h conf_core.h move.h macro.h obj_all.h \ + rotate.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h compat_misc.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/liblihata/genht/hash.h ../config.h \ + ../src_plugins/io_kicad/uniq_name.h ../src_3rd/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + compat_misc.h +../src_plugins/io_kicad/write.o: ../src_plugins/io_kicad/write.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h \ + ../src_plugins/io_kicad/uniq_name.h ../src_3rd/liblihata/genht/htsp.h \ + data.h crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 +../src_plugins/io_kicad_legacy/write.o: \ + ../src_plugins/io_kicad_legacy/write.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h error.h \ + ../src_plugins/io_kicad_legacy/../io_kicad/uniq_name.h \ + ../src_3rd/liblihata/genht/htsp.h data.h crosshair.h vtonpoint.h hid.h \ + error.h drc.h route.h buffer.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 vtptr.h \ + ../src_plugins/io_lihata/common.h polygon.h rtree.h conf_core.h \ + obj_all.h ../src_plugins/io_lihata/io_lihata.h conf.h \ + ../src_plugins/io_lihata/lht_conf.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 +../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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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 \ + 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h plug_io.h error.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + attrib.h change.h crosshair.h vtonpoint.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/liblihata/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/liblihata/genht/ht.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 error.h ../src_plugins/io_pcb/file.h board.h vtroutestyle.h \ + library.h rats_patch.h board.h plug_io.h hid.h layer.h move.h \ + ../src_plugins/io_pcb/parse_common.h pcb-printf.h polygon.h rtree.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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.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/liblihata/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/liblihata/genht/ht.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 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 +../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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 error.h ../src_plugins/io_pcb/file.h plug_io.h \ + ../src_plugins/io_pcb/parse_l.h polygon.h rtree.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/genht/htip.h ../src_3rd/liblihata/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 \ + 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/liblihata/genht/ht.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 ../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 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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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 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/liblihata/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/liblihata/genht/ht.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 error.h pcb-printf.h \ + ../src_3rd/genvector/gds_char.h compat_misc.h hid_actions.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.h \ + rats.h netlist.h route_style.h polygon.h rtree.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h misc_util.h obj_line.h event.h \ + dolists.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 \ + ../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 +../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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 hid_cfg_input.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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/compat.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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/compat.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 error.h search.h rats.h \ + netlist.h route_style.h draw.h layer.h pcb-printf.h undo.h \ + ../src_plugins/lib_gtk_common/dlg_drc.h \ + ../src_plugins/lib_gtk_common/glue.h hid.h conf.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/compat.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h conf_core.h buffer.h \ + data.h crosshair.h vtonpoint.h hid.h route.h const.h buffer.h const.h \ + plug_footprint.h vtlibrary.h compat_nls.h \ + ../src_plugins/lib_gtk_common/bu_box.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 \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_misc.h \ + ../src_plugins/lib_gtk_common/dlg_library_param.h plug_footprint.h \ + vtlibrary.h ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.h \ + ../src_plugins/lib_gtk_common/dlg_library.h hid.h \ + ../src_plugins/lib_gtk_common/glue.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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 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 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_common/compat.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h conf_core.h copy.h data.h \ + crosshair.h vtonpoint.h hid.h route.h const.h buffer.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 hid_cfg.h \ + ../src_plugins/lib_gtk_common/compat.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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 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 hid_cfg.h \ + ../src_plugins/lib_gtk_common/compat.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h attrib.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 hid_cfg_input.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/compat.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/genht/htip.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/genht/htip.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/ht.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 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 \ + ../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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/genht/htip.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/ht.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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/genht/htip.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/ht.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 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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h hid_actions.h hid.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h conf.h \ + ../src_plugins/lib_gtk_common/in_mouse.h hid_cfg_input.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htip.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/ht.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 \ + data.h crosshair.h vtonpoint.h hid.h route.h const.h buffer.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h conf.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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 ../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 hid_cfg.h \ + ../src_plugins/lib_gtk_common/glue.h \ + ../src_plugins/lib_gtk_common/compat.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h \ + ../src_plugins/lib_gtk_common/glue.h conf.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.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/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/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 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_drc.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.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/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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.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/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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 hid_cfg_input.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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.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/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/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_drc.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.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/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/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 action_helper.h change.h error.h \ + undo.h library.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/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h change.h error.h \ + undo.h library.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_attrib.h dolists.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 +../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h find.h polygon.h rtree.h search.h rats.h netlist.h \ + route_style.h vtroutestyle.h undo.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h change.h error.h \ + undo.h library.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 macro.h remove.h hid.h \ + error.h rtree.h polygon.h rtree.h polyarea.h flag_str.h find.h draw.h \ + undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 macro.h remove.h hid.h \ + error.h rtree.h draw.h polygon.h rtree.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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_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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h ../src_3rd/liblihata/genht/ht.c +../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 ../src_plugins/propedit/props.h \ + global_typedefs.h ../src_3rd/liblihata/genht/htsp.h \ + ../src_plugins/propedit/propsel.h change.h misc_util.h compat_misc.h \ + undo.h library.h rotate.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h move.h \ + pcb-printf.h remove.h rtree.h flag_str.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 ../src_plugins/query/query_access.h \ + ../src_plugins/query/query.h obj_any.h ../src_3rd/liblihata/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/liblihata/genht/hash.h ../src_3rd/liblihata/genht/htsi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/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 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/liblihata/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/liblihata/genht/ht.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 action_helper.h change.h error.h \ + undo.h library.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 \ + ../src_plugins/query/query_access.h ../src_plugins/query/query.h \ + obj_any.h ../src_3rd/liblihata/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 +../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/liblihata/genht/htsi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 ../src_plugins/query/query.h obj_any.h \ + ../src_3rd/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/liblihata/genht/htsi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.h \ + ../src_3rd/genlist/gentdlist_impl.h ../src_3rd/genlist/gendlist.h \ + ../src_3rd/genlist/gentdlist_undef.h ../src_3rd/liblihata/genht/htsi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 action_helper.h \ + change.h error.h undo.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h compat_nls.h \ + netlist.h route_style.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 ../src_plugins/report/drill.h macro.h \ + obj_pinvia.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 \ + ../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 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 ../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 error.h event.h undo.h \ + operation.h rotate.h draw.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 ../src_3rd/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h layer_grp.h \ + ../src_plugins/rubberband_orig/fgeometry.h obj_common.h polygon.h \ + rtree.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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/smartdisperse/smartdisperse.o: \ + ../src_plugins/smartdisperse/smartdisperse.c \ + ../src_3rd/liblihata/genht/htpi.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 hid.h rtree.h undo.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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 crosshair.h \ + stub_stroke.h rotate.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 hid.h rtree.h undo.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h error.h undo.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/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/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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/dom_internal.h ../src_3rd/liblihata/tree.h \ + ../src_3rd/liblihata/dom.h +../src_3rd/liblihata/genht/hash.o: ../src_3rd/liblihata/genht/hash.c +../src_3rd/liblihata/genht/htip.o: ../src_3rd/liblihata/genht/htip.c \ + ../src_3rd/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/genht/ht.c +../src_3rd/liblihata/genht/htpi.o: ../src_3rd/liblihata/genht/htpi.c \ + ../src_3rd/liblihata/genht/htpi.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/genht/ht.c +../src_3rd/liblihata/genht/htpp.o: ../src_3rd/liblihata/genht/htpp.c \ + ../src_3rd/liblihata/genht/htpp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/genht/ht.c +../src_3rd/liblihata/genht/htsi.o: ../src_3rd/liblihata/genht/htsi.c \ + ../src_3rd/liblihata/genht/htsi.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/genht/ht.c +../src_3rd/liblihata/genht/htsp.o: ../src_3rd/liblihata/genht/htsp.c \ + ../src_3rd/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h ../src_3rd/liblihata/genht/ht.c +../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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/dom_internal.h ../src_3rd/liblihata/tree.h \ + ../src_3rd/liblihata/dom.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h undo.h library.h compat_nls.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h find.h insert.h \ + polygon.h rtree.h remove.h rotate.h search.h rats.h netlist.h \ + route_style.h select.h operation.h undo.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 +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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h plug_io.h compat_misc.h \ + hid_actions.h paths.h rtree.h undo.h draw.h event.h defpcb_internal.c +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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h misc_util.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h attrib.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/liblihata/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/liblihata/genht/ht.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 plug_io.h polygon.h rtree.h rotate.h \ + remove.h select.h operation.h draw.h undo.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 event.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h select.h operation.h undo.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 +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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 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 ../src_3rd/genvector/gds_char.h \ + ../src_3rd/genvector/genvector_impl.h \ + ../src_3rd/genvector/genvector_undef.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 ../config.h compat_misc.h compat_inc.h +conf.o: conf.c ../src_3rd/liblihata/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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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 \ + ../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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/liblihata/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h select.h operation.h undo.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 +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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h search.h rats.h netlist.h \ + route_style.h polygon.h rtree.h hid_actions.h compat_misc.h compat_nls.h \ + find.h undo.h event.h action_helper.h obj_line_draw.h obj_arc_draw.h \ + obj_arc_ui.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 rtree.h list_common.h obj_all.h \ + layer_it.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h move.h misc_util.h ht_element.h ../src_3rd/liblihata/genht/ht.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 draw.h rotate.h rtree.h stub_draw.h obj_all.h layer_ui.h \ + obj_pad_draw.h obj_pinvia_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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h compat_nls.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 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 +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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 \ + draw.h find.h rtree.h polygon.h search.h rats.h netlist.h library.h \ + route_style.h vtroutestyle.h undo.h plug_io.h hid_actions.h \ + compat_misc.h event.h layer_vis.h obj_all.h find_geo.c find_lookup.c \ + compat_nls.h board.h rats_patch.h 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 find_misc.c 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 find.h compat_nls.h +flag.o: flag.c ../config.h flag.h globalconst.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/liblihata/genht/hash.h font.h \ + ../src_3rd/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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 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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h plug_io.h +fptr_cast.o: fptr_cast.c ../config.h fptr_cast.h +free_atexit.o: free_atexit.c ../config.h +funchash.o: funchash.c ../src_3rd/liblihata/genht/htpi.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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 action_helper.h undo.h funchash_core.h funchash.h \ + funchash_core_list.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/liblihata/genht/htsp.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 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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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 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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/genht/htip.h hid_cfg.h hid_cfg_action.h error.h \ + compat_misc.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h \ + obj_rat_list.h obj_rat.h layer_grp.h compat_misc.h \ + ../src_3rd/liblihata/genht/ht.c +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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h hid_flags.h ../src_3rd/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h attrib.h \ + global_typedefs.h pcb_bool.h unit.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht.c +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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 select.h operation.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h compat_misc.h undo.h event.h \ + layer_ui.h layer_vis.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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 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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h buffer.h crosshair.h vtonpoint.h \ + hid.h drc.h route.h compat_lrealpath.h free_atexit.h polygon.h rtree.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 vtptr.h layer_vis.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h select.h operation.h undo.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 +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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 polygon.h rtree.h undo.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h compat_misc.h obj_arc_op.h operation.h draw.h obj_arc_draw.h +obj_arc_list.o: obj_arc_list.c obj_arc_list.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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 const.h error.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + attrib.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/liblihata/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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h conf_core.h compat_nls.h compat_misc.h rotate.h remove.h \ + polygon.h rtree.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h \ + ../src_3rd/genlist/gentdlist_impl.c +obj_line.o: obj_line.c ../config.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 search.h rats.h netlist.h route_style.h polygon.h \ + rtree.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h compat_nls.h compat_misc.h rotate.h obj_line_op.h \ + operation.h draw.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h move.h misc_util.h ht_element.h ../src_3rd/liblihata/genht/ht.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 find.h rtree.h +obj_line_list.o: obj_line_list.c obj_line_list.h obj_line.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 undo.h polygon.h rtree.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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 undo.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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h polygon.h rtree.h compat_nls.h \ + compat_misc.h stub_vendor.h rotate.h obj_pinvia_op.h operation.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.h globalconst.h ../config.h attrib.h \ + global_typedefs.h pcb_bool.h unit.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 compat_nls.h undo.h polygon.h rtree.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/liblihata/genht/htsp.h ../src_3rd/genvector/vtp0.h \ + list_conf.h obj_poly_op.h operation.h obj_poly_draw.h draw.h +obj_poly_list.o: obj_poly_list.c obj_poly_list.h obj_poly.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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_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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 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/liblihata/genht/htsp.h \ + ../src_3rd/genvector/vtp0.h list_conf.h undo.h rtree.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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_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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 compat_misc.h compat_nls.h undo.h \ + polygon.h rtree.h event.h obj_text_op.h operation.h obj_poly_draw.h \ + obj_arc_draw.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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h ../config.h attrib.h global_typedefs.h pcb_bool.h unit.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 board.h vtroutestyle.h library.h \ + rats_patch.h action_helper.h change.h undo.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 +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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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 +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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.h \ + ../src_3rd/liblihata/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/liblihata/genht/htsp.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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 +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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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 data.h layer.h \ + attrib.h obj_all_list.h obj_arc_list.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 plug_io.h library.h remove.h \ + paths.h rats_patch.h board.h vtroutestyle.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 layer_vis.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h polygon.h rtree.h remove.h \ + search.h rats.h netlist.h route_style.h obj_pinvia_therm.h undo.h \ + compat_nls.h obj_all.h obj_poly_draw.h +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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h macro.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h undo.h funchash_core.h \ + funchash.h funchash_core_list.h polygon.h rtree.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h find.h polygon.h rtree.h rats.h \ + netlist.h route_style.h search.h undo.h stub_mincut.h compat_misc.h \ + compat_nls.h vtptr.h obj_rat_draw.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.h obj_text_list.h obj_rat_list.h obj_rat.h \ + layer_grp.h library.h ../src_3rd/liblihata/genht/htsp.h data.h \ + crosshair.h vtonpoint.h hid.h error.h drc.h route.h buffer.h copy.h \ + compat_misc.h compat_nls.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 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 +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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 action_helper.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 draw.h polygon.h rtree.h rotate.h \ + search.h rats.h netlist.h route_style.h select.h operation.h undo.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/liblihata/genht/htsp.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_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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h move.h misc_util.h ht_element.h ../src_3rd/liblihata/genht/ht.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 find.h polygon.h rtree.h undo.h obj_line_draw.h obj_arc_draw.h \ + obj_line_op.h operation.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/liblihata/genht/htsp.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h obj_poly.h polyarea.h obj_poly_list.h \ + box.h math_helper.h move.h ht_element.h ../src_3rd/liblihata/genht/ht.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h macro.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 find.h polygon.h rtree.h search.h rats.h \ + netlist.h route_style.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 draw.h search.h rats.h netlist.h \ + route_style.h select.h operation.h undo.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 ../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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h undo.h funchash_core.h \ + funchash.h funchash_core_list.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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_pinvia.h obj_common.h \ + ../src_3rd/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.h \ + globalconst.h attrib.h obj_pad.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 +undo.o: undo.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/liblihata/genht/hash.h ../src_3rd/genlist/gendlist.h flag.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/liblihata/genht/htip.h ../src_3rd/liblihata/genht/ht.h \ + ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/ht.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 draw.h insert.h \ + polygon.h rtree.h remove.h rotate.h search.h rats.h netlist.h \ + route_style.h undo.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/liblihata/genht/htsp.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/liblihata/genht/htsp.h \ + ../src_3rd/liblihata/genht/ht.h ../src_3rd/liblihata/genht/ht_inlines.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/liblihata/genht/hash.h \ + ../src_3rd/genlist/gendlist.h flag.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/liblihata/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/liblihata/genht/ht.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 action_helper.h funchash_core.h \ + funchash.h funchash_core_list.h undo.h polygon.h rtree.h search.h rats.h \ + netlist.h route_style.h obj_line_draw.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 +vtptr.o: vtptr.c vtptr.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.3/src/Makefile.in =================================================================== --- tags/1.2.3/src/Makefile.in (nonexistent) +++ tags/1.2.3/src/Makefile.in (revision 8969) @@ -0,0 +1,409 @@ +# 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 + 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 + free_atexit.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 + 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_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_text.o + obj_text_list.o + paths.o + pcb_bool.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 + search.o + select.o + select_act.o + stub_draw.o + stub_mincut.o + stub_stroke.o + stub_vendor.o + undo.o + undo_act.o + unit.o + vtlibrary.o + vtonpoint.o + vtptr.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/liblihata/genht/hash.o + ../src_3rd/liblihata/genht/htsp.o + ../src_3rd/liblihata/genht/htsi.o + ../src_3rd/liblihata/genht/htpi.o + ../src_3rd/liblihata/genht/htip.o + ../src_3rd/liblihata/genht/htpp.o + ../src_3rd/liblhtpers/lhtpers.o + ../src_3rd/genvector/gds_char.o + ../src_3rd/genvector/vtp0.o + ../src_3rd/genregex/regex_sei.o + ../src_3rd/genregex/regex_se.o + ../src_3rd/genregex/regex.o + ../src_3rd/qparse/qparse.o +@] + +put /local/pcb/LIBS_3RD [@ + ../src_3rd/puplug/libpuplug.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 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 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 + +# ---- 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 + +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 + +@] + +print [@ +##### module rules begin ##### + +@/local/pcb/RULES@ + +##### module rules end ##### + +pcblib_DATA= \ + default_font \ + default.pcb \ + pcb-menu-lesstif.lht \ + pcb-menu-gtk.lht \ + pcb-menu-mkey.lht + + +EXTRA_DIST= \ + default_font \ + default.pcb \ + 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: default.pcb + $(CQUOTE) -n default_pcb_internal < default.pcb > 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) "default.pcb" "$(DATADIR)/default.pcb" + $(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.3/src/action_act.c =================================================================== --- tags/1.2.3/src/action_act.c (nonexistent) +++ tags/1.2.3/src/action_act.c (revision 8969) @@ -0,0 +1,111 @@ +/* + * 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" + +/* 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 = 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.3/src/action_helper.c =================================================================== --- tags/1.2.3/src/action_helper.c (nonexistent) +++ tags/1.2.3/src/action_helper.c (revision 8969) @@ -0,0 +1,1274 @@ +/* + * 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" + + +static void GetGridLockCoordinates(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_POLYGON: + *x = ((pcb_polygon_t *) ptr2)->Points[0].X; + *y = ((pcb_polygon_t *) ptr2)->Points[0].Y; + break; + + case PCB_TYPE_LINE_POINT: + case PCB_TYPE_POLYGON_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; + } +} + +static void AttachForCopy(pcb_coord_t PlaceX, pcb_coord_t PlaceY) +{ + 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 + */ + GetGridLockCoordinates(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 ((conf_core.editor.mode != PCB_MODE_COPY) && 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 (conf_core.editor.mode != PCB_MODE_COPY && + (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); +} + + +/* --------------------------------------------------------------------------- */ + +/* %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 */ + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_point_t InsertedPoint; +pcb_layer_t *lastLayer; +static struct { + pcb_polygon_t *poly; + pcb_line_t line; +} fake; + +pcb_action_note_t Note; +int defer_updates = 0; +int defer_needs_update = 0; + + +static pcb_cardinal_t polyIndex = 0; +pcb_bool saved_mode = pcb_false; + +static void AdjustAttachedBox(void); + +void pcb_clear_warnings() +{ + conf_core.temp.rat_warn = pcb_false; + PCB_PIN_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, pin)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, pin); + DrawPin(pin); + } + } + PCB_ENDALL_LOOP; + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, via)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, via); + DrawVia(via); + } + } + PCB_END_LOOP; + PCB_PAD_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, pad)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, pad); + DrawPad(pad); + } + } + PCB_ENDALL_LOOP; + PCB_LINE_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, line)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, line); + DrawLine(layer, line); + } + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, arc)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, arc); + DrawArc(layer, arc); + } + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_WARN, polygon)) { + PCB_FLAG_CLEAR(PCB_FLAG_WARN, polygon); + DrawPolygon(layer, polygon); + } + } + PCB_ENDALL_LOOP; + + pcb_draw(); +} + +/* 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 (Note.Click) { + pcb_notify_crosshair_change(pcb_false); + Note.Click = pcb_false; + if (Note.Moving && !pcb_gui->shift_is_pressed()) { + 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, Note.X, Note.Y, pcb_true); + pcb_undo_save_serial(); + pcb_remove_selected(); + pcb_crosshair_save_mode(); + saved_mode = pcb_true; + pcb_crosshair_set_mode(PCB_MODE_PASTE_BUFFER); + } + else if (Note.Hit && !pcb_gui->shift_is_pressed()) { + pcb_box_t box; + + pcb_crosshair_save_mode(); + saved_mode = pcb_true; + pcb_crosshair_set_mode(pcb_gui->control_is_pressed()? PCB_MODE_COPY : PCB_MODE_MOVE); + pcb_crosshair.AttachedObject.Ptr1 = Note.ptr1; + pcb_crosshair.AttachedObject.Ptr2 = Note.ptr2; + pcb_crosshair.AttachedObject.Ptr3 = Note.ptr3; + pcb_crosshair.AttachedObject.Type = Note.Hit; + + if (pcb_crosshair.drags != NULL) { + free(pcb_crosshair.drags); + pcb_crosshair.drags = NULL; + } + pcb_crosshair.dragx = Note.X; + pcb_crosshair.dragy = Note.Y; + box.X1 = Note.X + PCB_SLOP * pcb_pixel_slop; + box.X2 = Note.X - PCB_SLOP * pcb_pixel_slop; + box.Y1 = Note.Y + PCB_SLOP * pcb_pixel_slop; + box.Y2 = Note.Y - PCB_SLOP * pcb_pixel_slop; + pcb_crosshair.drags = pcb_list_block(PCB, &box, &pcb_crosshair.drags_len); + pcb_crosshair.drags_current = 0; + AttachForCopy(Note.X, Note.Y); + } + else { + pcb_box_t box; + + Note.Hit = 0; + 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_notify_block(); + pcb_crosshair.AttachedBox.Point1.X = Note.X; + pcb_crosshair.AttachedBox.Point1.Y = Note.Y; + } + pcb_notify_crosshair_change(pcb_true); + } +} + +void pcb_release_mode(void) +{ + pcb_box_t box; + + if (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; + + 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 (Note.Moving) { + Note.Moving = 0; + 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. */ + Note.Hit = 0; + Note.Moving = 0; + } + else if (Note.Moving) { + pcb_undo_restore_serial(); + pcb_notify_mode(); + pcb_buffer_clear(PCB, PCB_PASTEBUFFER); + pcb_buffer_set_number(Note.Buffer); + Note.Moving = pcb_false; + Note.Hit = 0; + } + else if (Note.Hit) { + pcb_notify_mode(); + Note.Hit = 0; + } + else if (conf_core.editor.mode == PCB_MODE_ARROW) { + 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; + } + if (saved_mode) + pcb_crosshair_restore_mode(); + saved_mode = pcb_false; +} + +/* --------------------------------------------------------------------------- + * set new coordinates if in 'RECTANGLE' mode + * the cursor shape is also adjusted + */ +static void AdjustAttachedBox(void) +{ + if (conf_core.editor.mode == PCB_MODE_ARC) { + pcb_crosshair.AttachedBox.otherway = pcb_gui->shift_is_pressed(); + return; + } + 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; + } + } +} + +void pcb_adjust_attached_objects(void) +{ + pcb_point_t *pnt; + switch (conf_core.editor.mode) { + /* update at least an attached block (selection) */ + case PCB_MODE_NO: + case PCB_MODE_ARROW: + if (pcb_crosshair.AttachedBox.State) { + pcb_crosshair.AttachedBox.Point2.X = pcb_crosshair.X; + pcb_crosshair.AttachedBox.Point2.Y = pcb_crosshair.Y; + } + break; + + /* rectangle creation mode */ + case PCB_MODE_RECTANGLE: + case PCB_MODE_ARC: + AdjustAttachedBox(); + break; + + /* polygon creation mode */ + case PCB_MODE_POLYGON: + case PCB_MODE_POLYGON_HOLE: + pcb_line_adjust_attached(); + break; + /* line creation mode */ + case PCB_MODE_LINE: + pcb_line_adjust_attached(); + break; + /* point insertion mode */ + case PCB_MODE_INSERT_POINT: + pnt = pcb_adjust_insert_point(); + if (pnt) + InsertedPoint = *pnt; + break; + case PCB_MODE_ROTATE: + break; + } +} + +void pcb_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 && conf_core.editor.mode == PCB_MODE_LINE) { + 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 */ + lastLayer = CURRENT; + default: /* all following points */ + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_THIRD; + break; + } +} + +void pcb_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); +} + +void pcb_notify_mode(void) +{ + void *ptr1, *ptr2, *ptr3; + int type; + + if (conf_core.temp.rat_warn) + pcb_clear_warnings(); + switch (conf_core.editor.mode) { + case PCB_MODE_ARROW: + { + int test; + pcb_hidval_t hv; + + 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 + * (Note.Moving) or clicked on a MOVE_TYPE + * (Note.Hit) + */ + for (test = (PCB_SELECT_TYPES | PCB_MOVE_TYPES) & ~PCB_TYPE_RATLINE; test; test &= ~type) { + type = pcb_search_screen(Note.X, Note.Y, test, &ptr1, &ptr2, &ptr3); + if (!Note.Hit && (type & PCB_MOVE_TYPES) && !PCB_FLAG_TEST(PCB_FLAG_LOCK, (pcb_pin_t *) ptr2)) { + Note.Hit = type; + Note.ptr1 = ptr1; + Note.ptr2 = ptr2; + Note.ptr3 = ptr3; + } + if (!Note.Moving && (type & PCB_SELECT_TYPES) && PCB_FLAG_TEST(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr2)) + Note.Moving = pcb_true; + if ((Note.Hit && Note.Moving) || type == PCB_TYPE_NONE) + break; + } + break; + } + + case PCB_MODE_VIA: + { + pcb_pin_t *via; + + if (!PCB->ViaOn) { + pcb_message(PCB_MSG_WARNING, _("You must turn via visibility on before\n" "you can place vias\n")); + break; + } + if ((via = pcb_via_new(PCB->Data, Note.X, 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); + pcb_undo_inc_serial(); + DrawVia(via); + pcb_draw(); + } + break; + } + + case PCB_MODE_ARC: + { + switch (pcb_crosshair.AttachedBox.State) { + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedBox.Point1.X = pcb_crosshair.AttachedBox.Point2.X = Note.X; + pcb_crosshair.AttachedBox.Point1.Y = pcb_crosshair.AttachedBox.Point2.Y = 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 = Note.X - pcb_crosshair.AttachedBox.Point1.X; + wy = 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(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++; + DrawArc(CURRENT, arc); + pcb_draw(); + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_THIRD; + } + break; + } + } + break; + } + case PCB_MODE_LOCK: + { + type = pcb_search_screen(Note.X, 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 + */ + DrawElement(element); + pcb_draw(); + pcb_hid_actionl("Report", "Object", 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(type, ptr1, ptr2); + pcb_draw(); + } + pcb_hid_actionl("Report", "Object", NULL); + } + break; + } + case PCB_MODE_THERMAL: + { + if (((type = pcb_search_screen(Note.X, Note.Y, PCB_TYPEMASK_PIN, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) + && !PCB_FLAG_TEST(PCB_FLAG_HOLE, (pcb_pin_t *) 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); + } + else if (PCB_FLAG_THERM_GET(INDEXOFCURRENT, (pcb_pin_t *) ptr3)) + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, 0); + else + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, PCB->ThermStyle); + } + break; + } + + case PCB_MODE_LINE: + /* do update of position */ + pcb_notify_line(); + if (pcb_crosshair.AttachedLine.State != PCB_CH_STATE_THIRD) + break; + /* 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); + break; + } + + 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(); + DrawRat(line); + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + pcb_draw(); + } + break; + } + 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_(lastLayer) + && 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(PCB, pcb_layer_id(PCB->Data, CURRENT)) & PCB_LYT_COPPER) + && (pcb_layer_flags(PCB, pcb_layer_id(PCB->Data, lastLayer)) & PCB_LYT_COPPER) + && (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) + DrawVia(via); + + pcb_draw(); + pcb_undo_inc_serial(); + lastLayer = 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 != Note.X || pcb_crosshair.AttachedLine.Point2.Y != 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 = Note.X; + pcb_crosshair.AttachedLine.Point2.Y = Note.Y; + } + + if (conf_core.editor.auto_drc + && (pcb_layer_flags(PCB, pcb_layer_id(PCB->Data, 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(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); + DrawLine(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_(lastLayer) + && (pcb_layer_flags(PCB, pcb_layer_id(PCB->Data, CURRENT)) & PCB_LYT_COPPER) + && (pcb_layer_flags(PCB, pcb_layer_id(PCB->Data, lastLayer)) & PCB_LYT_COPPER) + && 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); + DrawVia(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(); + lastLayer = CURRENT; + } + if (conf_core.editor.line_refraction && (Note.X != pcb_crosshair.AttachedLine.Point2.X || Note.Y != pcb_crosshair.AttachedLine.Point2.Y) + && (line = + pcb_line_new_merge(CURRENT, + pcb_crosshair.AttachedLine.Point2.X, + pcb_crosshair.AttachedLine.Point2.Y, + Note.X, 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(); + DrawLine(CURRENT, line); + /* move to new start point */ + pcb_crosshair.AttachedLine.Point1.X = Note.X; + pcb_crosshair.AttachedLine.Point1.Y = Note.Y; + pcb_crosshair.AttachedLine.Point2.X = Note.X; + pcb_crosshair.AttachedLine.Point2.Y = 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 = Note.X; + pcb_marked.Y = Note.Y; + } + pcb_draw(); + } + break; + + case PCB_MODE_RECTANGLE: + /* do update of position */ + pcb_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_polygon_t *polygon; + + int flags = PCB_FLAG_CLEARPOLY; + if (conf_core.editor.full_poly) + flags |= PCB_FLAG_FULLPOLY; + if ((polygon = pcb_poly_new_from_rectangle(CURRENT, + pcb_crosshair.AttachedBox.Point1.X, + pcb_crosshair.AttachedBox.Point1.Y, + pcb_crosshair.AttachedBox.Point2.X, + pcb_crosshair.AttachedBox.Point2.Y, pcb_flag_make(flags))) != NULL) { + pcb_obj_add_attribs(polygon, PCB->pen_attr); + pcb_undo_add_obj_to_create(PCB_TYPE_POLYGON, CURRENT, polygon, polygon); + pcb_undo_inc_serial(); + DrawPolygon(CURRENT, polygon); + pcb_draw(); + } + + /* reset state to 'first corner' */ + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + } + break; + + case PCB_MODE_TEXT: + { + 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(CURRENT, pcb_font(PCB, conf_core.design.text_font_id, 1), Note.X, + 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(); + DrawText(CURRENT, text); + pcb_draw(); + } + } + free(string); + } + break; + } + + case PCB_MODE_POLYGON: + { + pcb_point_t *points = pcb_crosshair.AttachedPolygon.Points; + pcb_cardinal_t n = pcb_crosshair.AttachedPolygon.PointN; + + /* do update of position; use the 'PCB_MODE_LINE' mechanism */ + pcb_notify_line(); + + /* 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); + break; + } + + /* 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); + 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); + + /* 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 = Note.X; + pcb_marked.Y = Note.Y; + } + + break; + } + + case PCB_MODE_POLYGON_HOLE: + { + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(Note.X, Note.Y, PCB_TYPE_POLYGON, + &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_polygon_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; + pcb_polyarea_t *original, *new_hole, *result; + pcb_flag_t Flags; + + /* do update of position; use the 'PCB_MODE_LINE' mechanism */ + pcb_notify_line(); + + if (conf_core.editor.orthogonal_moves) { + /* set the mark to the new starting point so ortho works */ + pcb_marked.X = Note.X; + pcb_marked.Y = 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) { + /* Create pcb_polyarea_ts from the original polygon + * and the new hole polygon */ + original = pcb_poly_from_poly((pcb_polygon_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_polygon_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_POLYGON, + pcb_crosshair.AttachedObject.Ptr1, pcb_crosshair.AttachedObject.Ptr2, pcb_crosshair.AttachedObject.Ptr3); + pcb_undo_restore_serial(); + pcb_undo_inc_serial(); + pcb_draw(); + + /* reset state of attached line */ + memset(&pcb_crosshair.AttachedPolygon, 0, sizeof(pcb_polygon_t)); + pcb_crosshair.AttachedLine.State = PCB_CH_STATE_FIRST; + pcb_crosshair.AttachedObject.State = PCB_CH_STATE_FIRST; + pcb_added_lines = 0; + + 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); + + /* copy the coordinates */ + pcb_crosshair.AttachedLine.Point1.X = pcb_crosshair.AttachedLine.Point2.X; + pcb_crosshair.AttachedLine.Point1.Y = pcb_crosshair.AttachedLine.Point2.Y; + } + break; + } + } + break; + } + + case PCB_MODE_PASTE_BUFFER: + { + pcb_text_t estr[PCB_MAX_ELEMENTNAMES]; + pcb_element_t *e = 0; + + if (pcb_gui->shift_is_pressed()) { + int type = pcb_search_screen(Note.X, Note.Y, PCB_TYPE_ELEMENT, &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, Note.X, Note.Y)) + pcb_board_set_changed_flag(pcb_true); + if (e) { + int type = pcb_search_screen(Note.X, Note.Y, PCB_TYPE_ELEMENT, &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) + EraseElementName(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) + DrawElementName(e); + } + } + } + break; + } + + case PCB_MODE_REMOVE: + if ((type = pcb_search_screen(Note.X, Note.Y, PCB_REMOVE_TYPES, &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")); + break; + } + 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); + } + break; + + case PCB_MODE_ROTATE: + pcb_screen_obj_rotate90(Note.X, Note.Y, pcb_gui->shift_is_pressed()? (PCB_SWAP_IDENT ? 1 : 3) + : (PCB_SWAP_IDENT ? 3 : 1)); + break; + + /* both are almost the same */ + case PCB_MODE_COPY: + case PCB_MODE_MOVE: + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + { + int types = (conf_core.editor.mode == PCB_MODE_COPY) ? PCB_COPY_TYPES : PCB_MOVE_TYPES; + + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(Note.X, Note.Y, types, + &pcb_crosshair.AttachedObject.Ptr1, &pcb_crosshair.AttachedObject.Ptr2, &pcb_crosshair.AttachedObject.Ptr3); + if (pcb_crosshair.AttachedObject.Type != PCB_TYPE_NONE) { + if (conf_core.editor.mode == PCB_MODE_MOVE && 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 + AttachForCopy(Note.X, Note.Y); + } + break; + } + + /* second notify, move or copy object */ + case PCB_CH_STATE_SECOND: + if (conf_core.editor.mode == PCB_MODE_COPY) + pcb_copy_obj(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, + pcb_crosshair.AttachedObject.Ptr3, Note.X - pcb_crosshair.AttachedObject.X, Note.Y - pcb_crosshair.AttachedObject.Y); + else { + pcb_move_obj_and_rubberband(pcb_crosshair.AttachedObject.Type, + pcb_crosshair.AttachedObject.Ptr1, + pcb_crosshair.AttachedObject.Ptr2, + pcb_crosshair.AttachedObject.Ptr3, + Note.X - pcb_crosshair.AttachedObject.X, 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; + } + break; + + /* insert a point into a polygon/line/... */ + case PCB_MODE_INSERT_POINT: + switch (pcb_crosshair.AttachedObject.State) { + /* first notify, lookup object */ + case PCB_CH_STATE_FIRST: + pcb_crosshair.AttachedObject.Type = + pcb_search_screen(Note.X, 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_polygon_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_POLYGON) { + fake.poly = (pcb_polygon_t *) pcb_crosshair.AttachedObject.Ptr2; + polyIndex = pcb_poly_get_lowest_distance_point(fake.poly, Note.X, 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_POLYGON) + pcb_insert_point_in_object(PCB_TYPE_POLYGON, + 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; + } + break; + } +} + +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.3/src/action_helper.h =================================================================== --- tags/1.2.3/src/action_helper.h (nonexistent) +++ tags/1.2.3/src/action_helper.h (revision 8969) @@ -0,0 +1,84 @@ +/* + * 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 + * + */ + +/* prototypes for action routines */ + +#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; +extern pcb_layer_t *lastLayer; + + +void pcb_notify_line(void); /* creates points of a line (when clicked) */ +void pcb_notify_block(void); /* create first or second corner of a marked block (when clicked) */ + +/* 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); + +typedef struct { + pcb_coord_t X, Y; + pcb_cardinal_t Buffer; + pcb_bool Click; + pcb_bool Moving; /* selected type clicked on */ + int Hit; /* move type clicked on */ + void *ptr1; + void *ptr2; + void *ptr3; +} pcb_action_note_t; + +extern pcb_action_note_t Note; +extern pcb_bool saved_mode; + +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.3/src/attrib.c =================================================================== --- tags/1.2.3/src/attrib.c (nonexistent) +++ tags/1.2.3/src/attrib.c (revision 8969) @@ -0,0 +1,118 @@ +/* + * 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., 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 + * + */ + +/* attribute lists */ +#include +#include +#include "config.h" +#include "compat_misc.h" +#include "attrib.h" + +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 replace) +{ + int i; + + if ((name == NULL) || (*name == '\0')) + return -1; + + /* If we're allowed to replace an existing attribute, see if we + can. */ + if (replace) { + 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); + 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->Number++; + return 0; +} + +int pcb_attribute_remove_idx(pcb_attribute_list_t * list, int idx) +{ + int j; + free(list->List[idx].name); + free(list->List[idx].value); + for (j = idx; j < list->Number-1; j++) + list->List[j] = list->List[j + 1]; + list->Number--; + 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 replace) +{ + int i; + + for (i = 0; i < src->Number; i++) + pcb_attribute_put(dest, src->List[i].name, src->List[i].value, replace); +} + Index: tags/1.2.3/src/attrib.h =================================================================== --- tags/1.2.3/src/attrib.h (nonexistent) +++ tags/1.2.3/src/attrib.h (revision 8969) @@ -0,0 +1,69 @@ +/* + * 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., 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 + * + */ + +/* 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; +} pcb_attribute_t; + +struct pcb_attribute_list_s { + int Number, Max; + pcb_attribute_t *List; +}; + +/* 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); +/* Adds an attribute to the list. If the attribute already exists, + whether it's replaced or a second copy added depends on + REPLACE. Returns non-zero if an existing attribute was replaced. */ +int pcb_attribute_put(pcb_attribute_list_t * list, const char *name, const char *value, int replace); +/* 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, 1) +/* 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 eacg attribute from src to dest */ +void pcb_attribute_copy_all(pcb_attribute_list_t *dest, const pcb_attribute_list_t *src, int replace); + +#endif Index: tags/1.2.3/src/board.c =================================================================== --- tags/1.2.3/src/board.c (nonexistent) +++ tags/1.2.3/src/board.c (revision 8969) @@ -0,0 +1,317 @@ +/* + * 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 + * + */ +#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" + +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); + /* 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; + const char *tmp_fn = ".pcb-rnd.default.pcb"; + + /* We can parse from file only, make a temp file */ + f = fopen(tmp_fn, "wb"); + if (f != NULL) { + fwrite(default_pcb_internal, strlen(default_pcb_internal), 1, f); + fclose(f); + dpcb = pcb_load_pcb(tmp_fn, 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"); + remove(tmp_fn); + } + } + + 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].Color = conf_core.appearance.color.layer[i]; + ptr->Data->Layer[i].SelectedColor = conf_core.appearance.color.layer_selected[i]; + } +} + +typedef struct { + int nplated; + int nunplated; +} HoleCountStruct; + +static pcb_r_dir_t hole_counting_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; +} + +void pcb_board_count_holes(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_callback, &hcs, NULL); + pcb_r_search(PCB->Data->via_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); +} Index: tags/1.2.3/src/board.h =================================================================== --- tags/1.2.3/src/board.h (nonexistent) +++ tags/1.2.3/src/board.h (revision 8969) @@ -0,0 +1,169 @@ +/* + * 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 */ + 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(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)) + +const char *pcb_board_get_filename(void); +const char *pcb_board_get_name(void); + +/* 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); + +/* sets or resets changed flag and redraws status */ +void pcb_board_set_changed_flag(pcb_bool New); + +void pcb_board_changed(int reverted); + +#endif Index: tags/1.2.3/src/box.c =================================================================== --- tags/1.2.3/src/box.c (nonexistent) +++ tags/1.2.3/src/box.c (revision 8969) @@ -0,0 +1,85 @@ +/* + * 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 + * + */ + +#warning TODO: remove this and use genvect + +#define STEP_POINT 100 +#include +#include "config.h" +#include "rotate.h" +#include "box.h" + +/* --------------------------------------------------------------------------- + * get next slot for a box, allocates memory if necessary + */ +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 + */ +void pcb_box_free(pcb_box_list_t *Boxlist) +{ + if (Boxlist) { + free(Boxlist->Box); + memset(Boxlist, 0, sizeof(pcb_box_list_t)); + } +} + +/* --------------------------------------------------------------------------- + * sets the bounding box of a point (which is silly) + */ +void pcb_set_point_bounding_box(pcb_point_t *Pnt) +{ + Pnt->X2 = Pnt->X + 1; + Pnt->Y2 = Pnt->Y + 1; +} + +/* --------------------------------------------------------------------------- + * 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) +{ + 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.3/src/box.h =================================================================== --- tags/1.2.3/src/box.h (nonexistent) +++ tags/1.2.3/src/box.h (revision 8969) @@ -0,0 +1,232 @@ +/* + * 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. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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: + * 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) +/* some useful box utilities. */ + +#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*. */ +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED pcb_bool pcb_box_is_good(const pcb_box_t * b) +{ + return (b->X1 < b->X2) && (b->Y1 < b->Y2); +} + +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED 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; +} + +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED 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; +} + +static inline PCB_FUNC_UNUSED 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; +} + +static inline PCB_FUNC_UNUSED 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 */ +static inline PCB_FUNC_UNUSED 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 */ +static inline PCB_FUNC_UNUSED 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 */ +static inline PCB_FUNC_UNUSED 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 */ +static inline PCB_FUNC_UNUSED 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. */ +static inline PCB_FUNC_UNUSED 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); +} + +pcb_box_t *pcb_box_new(pcb_box_list_t *); +void pcb_box_free(pcb_box_list_t *); +void pcb_set_point_bounding_box(pcb_point_t *Pnt); +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.3/src/buffer.c =================================================================== --- tags/1.2.3/src/buffer.c (nonexistent) +++ tags/1.2.3/src/buffer.c (revision 8969) @@ -0,0 +1,885 @@ +/* + * 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., 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 + * + */ + +/* 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 "layer_grp.h" +#include "event.h" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t AddBufferFunctions = { + AddLineToBuffer, + AddTextToBuffer, + AddPolygonToBuffer, + AddViaToBuffer, + AddElementToBuffer, + NULL, + NULL, + NULL, + NULL, + NULL, + AddArcToBuffer, + AddRatToBuffer, + NULL +}; + +static pcb_opfunc_t MoveBufferFunctions = { + MoveLineToBuffer, + MoveTextToBuffer, + MovePolygonToBuffer, + MoveViaToBuffer, + MoveElementToBuffer, + NULL, + NULL, + NULL, + NULL, + NULL, + MoveArcToBuffer, + MoveRatToBuffer, + NULL +}; + +/* --------------------------------------------------------------------------- + * calculates the bounding box of the buffer + */ +int pcb_set_buffer_bbox(pcb_buffer_t *Buffer) +{ + pcb_box_t tmp, *box = pcb_data_bbox(&tmp, Buffer->Data); + + if (box) { + Buffer->BoundingBox = *box; + return 0; + } + return -1; +} + +/* --------------------------------------------------------------------------- + * clears the contents of the paste buffer + */ +void pcb_buffer_clear(pcb_board_t *pcb, pcb_buffer_t *Buffer) +{ + if (Buffer && Buffer->Data) { + pcb_data_free(Buffer->Data); + Buffer->Data->pcb = pcb; + } +} + +/* ---------------------------------------------------------------------- + * copies all selected and visible objects to the paste buffer + * returns true if any objects have been removed + */ +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_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, &AddBufferFunctions, &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; + } + pcb_notify_crosshair_change(pcb_true); +} + +/*---------------------------------------------------------------------------*/ + +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; + + if (!name) + PCB_ACT_FAIL(LoadFootprint); + + if (pcb_element_load_footprint_by_name(PCB_PASTEBUFFER, name)) + return 1; + + if (elementlist_length(&PCB_PASTEBUFFER->Data->Element) == 0) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains no elements", name); + return 1; + } + if (elementlist_length(&PCB_PASTEBUFFER->Data->Element) > 1) { + pcb_message(PCB_MSG_ERROR, "Footprint %s contains multiple elements", name); + return 1; + } + + e = elementlist_first(&PCB_PASTEBUFFER->Data->Element); + + 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; + + return 0; +} + +/* --------------------------------------------------------------------------- + * load PCB into buffer + * parse the file with enabled 'PCB mode' (see parser) + * if successful, update some other stuff + */ +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(1); + + /* 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_board_remove(newPCB); + Buffer->Data->pcb = pcb; + 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) + Buffer->Data->pcb = pcb; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); /* undo the events generated on load */ + return (pcb_false); +} + +/* --------------------------------------------------------------------------- + * rotates the contents of the pastebuffer + */ +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; + + /* 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; + + /* 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); +} + +/* --------------------------------------------------------------------------- + * creates a new paste buffer + */ +pcb_data_t *pcb_buffer_new(pcb_board_t *pcb) +{ + pcb_data_t *data; + data = (pcb_data_t *) calloc(1, sizeof(pcb_data_t)); + data->pcb = (pcb_board_t *)pcb; + return data; +} + + +/* -------------------------------------------------------------------------- */ + +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; +} + +/* --------------------------------------------------------------------------- + * initializes the buffers by allocating memory + */ +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(pcb); +} + +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); + 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_VIA_LOOP(Buffer->Data); + { + pcb_via_mirror(Buffer->Data, via); + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(Buffer->Data); + { + pcb_line_mirror(layer, line); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Buffer->Data); + { + pcb_arc_mirror(layer, arc); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Buffer->Data); + { + pcb_poly_mirror(layer, polygon); + } + PCB_ENDALL_LOOP; + pcb_set_buffer_bbox(Buffer); +} + + +/* --------------------------------------------------------------------------- + * flip components/tracks from one side to the other + */ +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; + /* 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); + } + PCB_ENDALL_LOOP; + + /* swap silkscreen layers */ + pcb_layer_list(PCB_LYT_BOTTOM | PCB_LYT_SILK, &SLayer, 1); + pcb_layer_list(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(); +} + +/* ---------------------------------------------------------------------- + * moves the passed object to the passed buffer and removes it + * from its original place + */ +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)); +} + +/* ---------------------------------------------------------------------- + * Adds the passed object to the passed buffer + */ +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)); +} + +/* --------------------------------------------------------------------------- + * 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) +{ + 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; + + /* paste all layers */ + num_layers = PCB_PASTEBUFFER->Data->LayerN; + if (num_layers == 0) /* some buffers don't have layers, just simple objects */ + num_layers = pcb->Data->LayerN; + for (i = 0; i < num_layers; i++) { + pcb_layer_t *sourcelayer = &PCB_PASTEBUFFER->Data->Layer[i], *destlayer = LAYER_PTR(i); + + if (destlayer->On) { + PCB_LINE_LOOP(sourcelayer); + { + if (CopyLine(&ctx, destlayer, line)) + changed = 1; + } + PCB_END_LOOP; + PCB_ARC_LOOP(sourcelayer); + { + if (CopyArc(&ctx, destlayer, arc)) + changed = 1; + } + PCB_END_LOOP; + PCB_TEXT_LOOP(sourcelayer); + { + if (CopyText(&ctx, destlayer, text)) + changed = 1; + } + PCB_END_LOOP; + PCB_POLY_LOOP(sourcelayer); + { + if (CopyPolygon(&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) { + CopyElement(&ctx, element); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + + /* finally the vias */ + if (pcb->ViaOn) { + changed |= (pinlist_length(&(PCB_PASTEBUFFER->Data->Via)) != 0); + PCB_VIA_LOOP(PCB_PASTEBUFFER->Data); + { + CopyVia(&ctx, via); + } + 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; + + /* converts buffer contents into an element */ + case F_Convert: + pcb_element_convert_from_buffer(PCB_PASTEBUFFER); + break; + + /* break up element for editing */ + case F_Restore: + pcb_element_smash_buffer(PCB_PASTEBUFFER); + 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: + if (elementlist_length(&PCB_PASTEBUFFER->Data->Element) == 0) { + pcb_message(PCB_MSG_ERROR, _("Buffer has no elements!\n")); + break; + } + 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 = 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.3/src/buffer.h =================================================================== --- tags/1.2.3/src/buffer.h (nonexistent) +++ tags/1.2.3/src/buffer.h (revision 8969) @@ -0,0 +1,80 @@ +/* + * 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 + * + */ + +/* prototypes for buffer handling routines */ + +#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 */ + /* are used */ +}; + +/* --------------------------------------------------------------------------- + * prototypes + */ +void pcb_buffer_flip_side(pcb_board_t *pcb, pcb_buffer_t *Buffer); + +/* returns 0 on success */ +int pcb_set_buffer_bbox(pcb_buffer_t *); + +void pcb_buffer_clear(pcb_board_t *pcb, pcb_buffer_t *); +void pcb_buffer_add_selected(pcb_board_t *pcb, pcb_buffer_t *, pcb_coord_t, pcb_coord_t, pcb_bool); +pcb_bool pcb_buffer_load_layout(pcb_board_t *pcb, pcb_buffer_t *Buffer, const char *Filename, const char *fmt); +void pcb_buffer_rotate(pcb_buffer_t *, pcb_uint8_t); +void pcb_buffer_select_paste(int); +void pcb_buffers_flip_side(pcb_board_t *pcb); +void pcb_buffer_mirror(pcb_board_t *pcb, pcb_buffer_t *); +void pcb_init_buffers(pcb_board_t *pcb); +void pcb_uninit_buffers(pcb_board_t *pcb); +void *pcb_move_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *, pcb_data_t *, int, void *, void *, void *); +void *pcb_copy_obj_to_buffer(pcb_board_t *pcb, pcb_data_t *, pcb_data_t *, int, void *, void *, void *); + +/* 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); + + +pcb_data_t *pcb_buffer_new(pcb_board_t *pcb); + +/* sets currently active buffer */ +void pcb_buffer_set_number(int Number); + + +/* --------------------------------------------------------------------------- + * access macro for current buffer + */ +#define PCB_PASTEBUFFER (&pcb_buffers[conf_core.editor.buffer_number]) + +#endif Index: tags/1.2.3/src/build_run.c =================================================================== --- tags/1.2.3/src/build_run.c (nonexistent) +++ tags/1.2.3/src/build_run.c (revision 8969) @@ -0,0 +1,286 @@ +/* + * 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., 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 + * + */ + +#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"); + gds_append_str(&info, "pcb-rnd forked from gEDA/PCB."); + gds_append_str(&info, "\n\n" "PCB is by harry eaton and others\n\n"); + gds_append_str(&info, "pcb-rnd is a refactored version "); + gds_append_str(&info, "with many new features and improvements.\n\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, "Copyright (C) Thomas Nau 1994, 1995, 1996, 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, 2004, 2005, 2006, 2007, 2008\n"); + gds_append_str(&info, "Copyright (C) Dan McMahill 2003, 2004, 2005, 2006, 2007, 2008\n\n"); + gds_append_str(&info, "Copyright (C) Tibor Palinkas 2013-2017 (pcb-rnd patches)"); + } + return info.array; +} + +/** pcb_get_info_websites: + * Returns a string that has a bunch of information about the websites. + */ +char *pcb_get_info_websites(void) +{ + static gds_t info; + static int first_time = 1; + + if (first_time) { + first_time = 0; + gds_init(&info); + + gds_append_str(&info, "For more information see:\n"); + gds_append_str(&info, "PCB-rnd homepage: http://repo.hu/projects/pcb-rnd\n"); + gds_append_str(&info, "PCB homepage: http://pcb.geda-project.org\n"); + gds_append_str(&info, "gEDA homepage: http://www.geda-project.org\n"); + gds_append_str(&info, "gEDA Wiki: http://wiki.geda-project.org\n\n"); + } + 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(); + 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, "It 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(); + 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.3/src/build_run.h =================================================================== --- tags/1.2.3/src/build_run.h (nonexistent) +++ tags/1.2.3/src/build_run.h (revision 8969) @@ -0,0 +1,39 @@ +/* + * 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., 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 + * + */ + +void pcb_quit_app(void); + +char *pcb_get_info_program(void); +char *pcb_get_info_copyright(void); +char *pcb_get_info_websites(void); +char *pcb_get_info_comments(void); +char *pcb_get_info_compile_options(void); + +char *pcb_get_infostr(void); + +const char *pcb_author(void); + +void pcb_catch_signal(int Signal); Index: tags/1.2.3/src/buildin.h =================================================================== --- tags/1.2.3/src/buildin.h (nonexistent) +++ tags/1.2.3/src/buildin.h (revision 8969) @@ -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.3/src/change.c =================================================================== --- tags/1.2.3/src/change.c (nonexistent) +++ tags/1.2.3/src/change.c (revision 8969) @@ -0,0 +1,1249 @@ +/* + * 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., 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 + * + */ + +/* 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" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t ChangeSizeFunctions = { + ChangeLineSize, + ChangeTextSize, + ChangePolyClear, + ChangeViaSize, + ChangeElementSize, /* changes silk screen line width */ + ChangeElementNameSize, + ChangePinSize, + ChangePadSize, + NULL, + NULL, + ChangeArcSize, + NULL, + NULL +}; + +static pcb_opfunc_t Change1stSizeFunctions = { + ChangeLineSize, + ChangeTextSize, + ChangePolyClear, + ChangeViaSize, + ChangeElement1stSize, + ChangeElementNameSize, + ChangePinSize, + ChangePadSize, + NULL, + NULL, + ChangeArcSize, + NULL, + NULL +}; + +static pcb_opfunc_t Change2ndSizeFunctions = { + NULL, + NULL, + NULL, + ChangeVia2ndSize, + ChangeElement2ndSize, + NULL, + ChangePin2ndSize, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeThermalFunctions = { + NULL, + NULL, + NULL, + ChangeViaThermal, + NULL, + NULL, + ChangePinThermal, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeClearSizeFunctions = { + ChangeLineClearSize, + NULL, + ChangePolygonClearSize, /* just to tell the user not to :-) */ + ChangeViaClearSize, + ChangeElementClearSize, + NULL, + ChangePinClearSize, + ChangePadClearSize, + NULL, + NULL, + ChangeArcClearSize, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeNameFunctions = { + ChangeLineName, + ChangeTextName, + NULL, + ChangeViaName, + ChangeElementName, + NULL, + ChangePinName, + ChangePadName, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangePinnumFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ChangePinNum, + ChangePadNum, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeSquareFunctions = { + NULL, + NULL, + NULL, + ChangeViaSquare, + ChangeElementSquare, + NULL, + ChangePinSquare, + ChangePadSquare, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeNonetlistFunctions = { + NULL, + NULL, + NULL, + NULL, + ChangeElementNonetlist, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeJoinFunctions = { + ChangeLineJoin, + ChangeTextJoin, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ChangeArcJoin, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeOctagonFunctions = { + NULL, + NULL, + NULL, + ChangeViaOctagon, + ChangeElementOctagon, + NULL, + ChangePinOctagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeMaskSizeFunctions = { + NULL, + NULL, + NULL, + ChangeViaMaskSize, +#if 0 + ChangeElementMaskSize, +#else + NULL, +#endif + NULL, + ChangePinMaskSize, + ChangePadMaskSize, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t SetSquareFunctions = { + NULL, + NULL, + NULL, + NULL, + SetElementSquare, + NULL, + SetPinSquare, + SetPadSquare, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t SetJoinFunctions = { + SetLineJoin, + SetTextJoin, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + SetArcJoin, + NULL, + NULL +}; + +static pcb_opfunc_t SetOctagonFunctions = { + NULL, + NULL, + NULL, + SetViaOctagon, + SetElementOctagon, + NULL, + SetPinOctagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ClrSquareFunctions = { + NULL, + NULL, + NULL, + NULL, + ClrElementSquare, + NULL, + ClrPinSquare, + ClrPadSquare, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ClrJoinFunctions = { + ClrLineJoin, + ClrTextJoin, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ClrArcJoin, + NULL, + NULL +}; + +static pcb_opfunc_t ClrOctagonFunctions = { + NULL, + NULL, + NULL, + ClrViaOctagon, + ClrElementOctagon, + NULL, + ClrPinOctagon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeRadiusFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ChangeArcRadius, + NULL, + NULL +}; + +static pcb_opfunc_t ChangeAngleFunctions = { + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + ChangeArcAngle, + NULL, + NULL +}; + +/* ---------------------------------------------------------------------- + * 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) +{ + pcb_bool change = pcb_false; + pcb_opctx_t ctx; + + ctx.chgtherm.pcb = PCB; + ctx.chgtherm.style = therm_style; + + change = pcb_selected_operation(PCB, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = Difference; + + change = pcb_selected_operation(PCB, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = Difference; + + if (pcb_mask_on(PCB)) + change = pcb_selected_operation(PCB, &ChangeMaskSizeFunctions, &ctx, pcb_false, types); + else + change = pcb_selected_operation(PCB, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = Difference; + + change = pcb_selected_operation(PCB, &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, &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, &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, &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, &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, &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, &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, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgangle.delta = Difference; + + change = pcb_selected_operation(PCB, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = Difference; + + change = pcb_selected_operation(PCB, &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, &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, &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, &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, &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, &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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = 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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = 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.absolute = (fixIt) ? r : 0; + ctx.chgsize.delta = 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.delta) + * 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.absolute = (fixIt) ? a : 0; + ctx.chgangle.delta = 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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = 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) +{ + pcb_bool change; + pcb_opctx_t ctx; + + ctx.chgtherm.pcb = PCB; + ctx.chgtherm.style = therm_type; + + 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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = 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.absolute = (fixIt) ? Difference : 0; + ctx.chgsize.delta = 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.absolute = 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]; + + /* 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; + } + 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; + } + 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); +} Index: tags/1.2.3/src/change.h =================================================================== --- tags/1.2.3/src/change.h (nonexistent) +++ tags/1.2.3/src/change.h (revision 8969) @@ -0,0 +1,110 @@ +/* + * 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 + * + */ + +/* prototypes to change object properties */ + +#ifndef PCB_CHANGE_H +#define PCB_CHANGE_H + +#include "config.h" + +/* --------------------------------------------------------------------------- + * some defines + */ +#define PCB_CHANGENAME_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_LINE) + +#define PCB_CHANGESIZE_TYPES \ + (PCB_TYPE_POLYGON | 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) + +#define PCB_CHANGE2NDSIZE_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_PIN | PCB_TYPE_ELEMENT) + +/* 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_POLYGON) + +#define PCB_CHANGENONETLIST_TYPES \ + (PCB_TYPE_ELEMENT) + +#define PCB_CHANGESQUARE_TYPES \ + (PCB_TYPE_ELEMENT | PCB_TYPE_PIN | PCB_TYPE_PAD | PCB_TYPE_VIA) + +#define PCB_CHANGEOCTAGON_TYPES \ + (PCB_TYPE_ELEMENT | PCB_TYPE_PIN | PCB_TYPE_VIA) + +#define PCB_CHANGEJOIN_TYPES \ + (PCB_TYPE_ARC | PCB_TYPE_LINE | PCB_TYPE_TEXT) + +#define PCB_CHANGETHERMAL_TYPES \ + (PCB_TYPE_PIN | PCB_TYPE_VIA) + +#define PCB_CHANGEMASKSIZE_TYPES \ + (PCB_TYPE_PIN | PCB_TYPE_VIA | PCB_TYPE_PAD) + +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, int); +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, void *, void *, void *, int); +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); + +#endif Index: tags/1.2.3/src/change_act.c =================================================================== --- tags/1.2.3/src/change_act.c (nonexistent) +++ tags/1.2.3/src/change_act.c (revision 8969) @@ -0,0 +1,1566 @@ +/* + * 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_POLYGON)) /* 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; + + if ((type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.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) + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.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(pcb_crosshair.X, pcb_crosshair.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." + "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; + + if (function && *function && style && *style) { + pcb_bool absolute; + + kind = pcb_get_value(style, NULL, &absolute, NULL); + if (absolute) + switch (pcb_funchash_get(function, NULL)) { + case F_Object: + if ((type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_CHANGETHERMAL_TYPES, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + pcb_chg_obj_thermal(type, ptr1, ptr2, ptr3, kind); + pcb_undo_inc_serial(); + pcb_draw(); + } + break; + case F_SelectedPins: + pcb_chg_selected_thermals(PCB_TYPE_PIN, kind); + break; + case F_SelectedVias: + pcb_chg_selected_thermals(PCB_TYPE_VIA, kind); + break; + case F_Selected: + case F_SelectedElements: + pcb_chg_selected_thermals(PCB_CHANGETHERMAL_TYPES, kind); + 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 /= 45; + 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) + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.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) + type = pcb_search_screen(pcb_crosshair.X, pcb_crosshair.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.3/src/clip.c =================================================================== --- tags/1.2.3/src/clip.c (nonexistent) +++ tags/1.2.3/src/clip.c (revision 8969) @@ -0,0 +1,110 @@ +/* + * 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., 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 + * + */ + +#include "config.h" +#include "clip.h" + +/* 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.3/src/clip.h =================================================================== --- tags/1.2.3/src/clip.h (nonexistent) +++ tags/1.2.3/src/clip.h (revision 8969) @@ -0,0 +1,44 @@ +/* + * 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., 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 + * + */ + +/* prototypes for inserting points into objects */ + +#ifndef PCB_CLIP_H +#define PCB_CLIP_H + +#include "global_typedefs.h" + +/* --------------------------------------------------------------------------- + * prototypes + */ + +/* 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.3/src/compat_cc.h =================================================================== --- tags/1.2.3/src/compat_cc.h (nonexistent) +++ tags/1.2.3/src/compat_cc.h (revision 8969) @@ -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.3/src/compat_fs.c =================================================================== --- tags/1.2.3/src/compat_fs.c (nonexistent) +++ tags/1.2.3/src/compat_fs.c (revision 8969) @@ -0,0 +1,310 @@ +/* + * 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., 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 + * + */ + + +/* 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 + +#include "error.h" + +/* ---------------------------------------------------------------------- + * 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) +{ +#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 = 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 +} + + +/* + * Creates a new temporary file name. 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; +} + +/* + * Unlink a temporary file. 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); +} Index: tags/1.2.3/src/compat_fs.h =================================================================== --- tags/1.2.3/src/compat_fs.h (nonexistent) +++ tags/1.2.3/src/compat_fs.h (revision 8969) @@ -0,0 +1,17 @@ +char *pcb_get_wd(char *); + +int pcb_mkdir(const char *path, int mode); +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); + +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); Index: tags/1.2.3/src/compat_inc.h.in =================================================================== --- tags/1.2.3/src/compat_inc.h.in (nonexistent) +++ tags/1.2.3/src/compat_inc.h.in (revision 8969) @@ -0,0 +1,38 @@ +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@ +@] + +put /tmpasm/IFS {\n} +uniq /local/pcb/compat_inc +gsub /local/pcb/compat_inc {\\\\n *} {\n} + + +print [@ +/*** DO NOT EDIT - automatically generated by scconfig ***/ + +/* 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 + +@] + Index: tags/1.2.3/src/compat_lrealpath.c =================================================================== --- tags/1.2.3/src/compat_lrealpath.c (nonexistent) +++ tags/1.2.3/src/compat_lrealpath.c (revision 8969) @@ -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.3/src/compat_lrealpath.h =================================================================== --- tags/1.2.3/src/compat_lrealpath.h (nonexistent) +++ tags/1.2.3/src/compat_lrealpath.h (revision 8969) @@ -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.3/src/compat_misc.c =================================================================== --- tags/1.2.3/src/compat_misc.c (nonexistent) +++ tags/1.2.3/src/compat_misc.c (revision 8969) @@ -0,0 +1,180 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" + + + +#include +#include +#include +#include +#include +#include "compat_misc.h" +#include "compat_inc.h" +#ifdef HAVE_UNISTD_H +#include +#endif + +/* 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 +} + Index: tags/1.2.3/src/compat_misc.h =================================================================== --- tags/1.2.3/src/compat_misc.h (nonexistent) +++ tags/1.2.3/src/compat_misc.h (revision 8969) @@ -0,0 +1,48 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef PCB_COMPAT_MISC_H +#define PCB_COMPAT_MISC_H + +#include "config.h" + +#include +#include + +long pcb_rand(void); + +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); + +#endif /* PCB_COMPAT_MISC_H */ Index: tags/1.2.3/src/compat_nls.h =================================================================== --- tags/1.2.3/src/compat_nls.h (nonexistent) +++ tags/1.2.3/src/compat_nls.h (revision 8969) @@ -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.3/src/conf.c =================================================================== --- tags/1.2.3/src/conf.c (nonexistent) +++ tags/1.2.3/src/conf.c (revision 8969) @@ -0,0 +1,1871 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* 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; + pcb_path_resolve(fn, &efn, 0); + f = fopen(efn, "r"); + 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\n", 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]; + static const char *project_name = "project.lht"; + FILE *f; + + 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 = fopen(res, "r"); + if (f != NULL) { + fclose(f); + 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) +{ + 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, val_change_pre); + conf_hid_local_cb((conf_native_t *)e->value, 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) { + *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_); + + free(path_); + return; + } + conf_field_clear(n); + conf_hid_global_cb(n, val_change_pre); + conf_hid_local_cb(n, 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, val_change_post); + conf_hid_global_cb((conf_native_t *)e->value, val_change_post); + } + } + else { + conf_hid_local_cb(n, val_change_post); + conf_hid_global_cb(n, 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); +} + +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); + 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); + 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; + } + } + + pcb_path_resolve(fn, &efn, 0); + + if (r != NULL) { + FILE *f; + f = fopen(efn, "w"); + + if ((f == NULL) && (role == CFR_USER)) { + /* create the directory and try again */ + char *path = pcb_strdup(efn), *end; + 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); + f = fopen(efn, "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 = 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); +} Index: tags/1.2.3/src/conf.h =================================================================== --- tags/1.2.3/src/conf.h (nonexistent) +++ tags/1.2.3/src/conf.h (revision 8969) @@ -0,0 +1,369 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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); + +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); + +#endif Index: tags/1.2.3/src/conf_act.c =================================================================== --- tags/1.2.3/src/conf_act.c (nonexistent) +++ tags/1.2.3/src/conf_act.c (revision 8969) @@ -0,0 +1,339 @@ +/* + * COPYRIGHT + * + * PCB, 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., 675 Mass Ave, Cambridge, MA 02139, 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]); + } + + 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]); + } + + 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 TODO: convert this to a compile-time hash + 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.3/src/conf_core.c =================================================================== --- tags/1.2.3/src/conf_core.c (nonexistent) +++ tags/1.2.3/src/conf_core.c (revision 8969) @@ -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; +} + +static void 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); + conf_ro("rc/have_regex"); + + conf_force_set_str(conf_core.rc.path.prefix, PCB_PREFIX); conf_ro("rc/path/prefix"); + conf_force_set_str(conf_core.rc.path.lib, PCBLIBDIR); conf_ro("rc/path/lib"); + conf_force_set_str(conf_core.rc.path.bin, BINDIR); conf_ro("rc/path/bin"); + conf_force_set_str(conf_core.rc.path.share, PCBSHAREDIR); conf_ro("rc/path/share"); + conf_force_set_str(conf_core.rc.path.home, get_homedir()); conf_ro("rc/path/home"); +} Index: tags/1.2.3/src/conf_core.h =================================================================== --- tags/1.2.3/src/conf_core.h (nonexistent) +++ tags/1.2.3/src/conf_core.h (revision 8969) @@ -0,0 +1,217 @@ +#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 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 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 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 */ + 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 backup_name; /* file name template for periodic backup anonymous .pcb files; optional fields: %P --> pid */ + + 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. */ + + /***** 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]) */ + } 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 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(); +#endif Index: tags/1.2.3/src/conf_hid.c =================================================================== --- tags/1.2.3/src/conf_hid.c (nonexistent) +++ tags/1.2.3/src/conf_hid.c (revision 8969) @@ -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, 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); + } + } + + free(h); +} + +typedef void (*cb_t)(conf_native_t *cfg); +void conf_hid_global_cb_(conf_native_t *item, 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); + } + } +} + + +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.3/src/conf_hid.h =================================================================== --- tags/1.2.3/src/conf_hid.h (nonexistent) +++ tags/1.2.3/src/conf_hid.h (revision 8969) @@ -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); + void (*val_change_post)(conf_native_t *cfg); + + /* Called when a new config item is added to the database; global-only */ + void (*new_item_post)(conf_native_t *cfg); + + /* Called during conf_hid_unreg to get hid-data cleaned up */ + void (*unreg_item)(conf_native_t *cfg); +} 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, 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); \ + } \ +} while(0) + +/* Call the local callback of a native item */ +#define conf_hid_global_cb(native, cb) \ +do { \ + conf_hid_callbacks_t __cbs__; \ + int __offs__ = ((char *)&(__cbs__.cb)) - ((char *)&(__cbs__)); \ + conf_hid_global_cb_(native, __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 offs); + +#endif Index: tags/1.2.3/src/const.h =================================================================== --- tags/1.2.3/src/const.h (nonexistent) +++ tags/1.2.3/src/const.h (revision 8969) @@ -0,0 +1,94 @@ +/* + * 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 + * + */ + +/* global source constants */ + +#ifndef PCB_CONST_H +#define PCB_CONST_H + +/* These need to be carefully written to avoid overflows, and return + a Coord type. */ +#define PCB_SCALE_TEXT(COORD,TEXTSCALE) ((pcb_coord_t)((COORD) * ((double)(TEXTSCALE) / 100.0))) +#define PCB_UNPCB_SCALE_TEXT(COORD,TEXTSCALE) ((pcb_coord_t)((COORD) * (100.0 / (double)(TEXTSCALE)))) + +/* --------------------------------------------------------------------------- + * modes + */ +typedef enum { + PCB_MODE_NO = 0, /* no mode selected - panning */ + PCB_MODE_VIA = 1, /* draw vias */ + PCB_MODE_LINE = 2, /* draw lines */ + PCB_MODE_RECTANGLE = 3, /* create rectangles */ + PCB_MODE_POLYGON = 4, /* draw filled polygons */ + PCB_MODE_PASTE_BUFFER = 5, /* paste objects from buffer */ + PCB_MODE_TEXT = 6, /* create text objects */ + PCB_MODE_ROTATE = 102, /* rotate objects */ + PCB_MODE_REMOVE = 103, /* remove objects */ + PCB_MODE_MOVE = 104, /* move objects */ + PCB_MODE_COPY = 105, /* copy objects */ + PCB_MODE_INSERT_POINT = 106, /* insert point into line/polygon */ + PCB_MODE_RUBBERBAND_MOVE = 107, /* move objects and attached lines */ + PCB_MODE_THERMAL = 108, /* toggle thermal layer flag */ + PCB_MODE_ARC = 109, /* draw arcs */ + PCB_MODE_ARROW = 110, /* selection with arrow mode */ + PCB_MODE_LOCK = 111, /* lock/unlock objects */ + PCB_MODE_POLYGON_HOLE = 112 /* 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_POLYGON = 0x00008, + PCB_TYPE_TEXT = 0x00010, + PCB_TYPE_RATLINE = 0x00020, + + 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_POLYGON_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_NET = 0x20000, /* used to select whole net. */ + + PCB_TYPE_ARC_POINT = 0x40000, + + /* groups/properties */ + PCB_TYPEMASK_PIN = (PCB_TYPE_VIA | PCB_TYPE_PIN), + PCB_TYPEMASK_LOCK = (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLYGON | PCB_TYPE_ELEMENT | 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.3/src/copy.c =================================================================== --- tags/1.2.3/src/copy.c (nonexistent) +++ tags/1.2.3/src/copy.c (revision 8969) @@ -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., 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 + * + */ + +/* 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" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t CopyFunctions = { + CopyLine, + CopyText, + CopyPolygon, + CopyVia, + CopyElement, + NULL, + NULL, + NULL, + NULL, + NULL, + CopyArc, + NULL, + NULL +}; + +/* --------------------------------------------------------------------------- + * copies the object identified by its data pointers and the type + * the new objects is moved by DX,DY + * I assume that the appropriate layer ... is switched on + */ +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; + + /* 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.3/src/copy.h =================================================================== --- tags/1.2.3/src/copy.h (nonexistent) +++ tags/1.2.3/src/copy.h (revision 8969) @@ -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., 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 + * + */ + +/* prototypes for copy routines */ + +#ifndef PCB_COPY_H +#define PCB_COPY_H + +#include "config.h" + +/* --------------------------------------------------------------------------- + * some defines + */ +#define PCB_COPY_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_TEXT | \ + PCB_TYPE_ELEMENT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_POLYGON | PCB_TYPE_ARC) + +void *pcb_copy_obj(int, void *, void *, void *, pcb_coord_t, pcb_coord_t); + +#endif Index: tags/1.2.3/src/crosshair.c =================================================================== --- tags/1.2.3/src/crosshair.c (nonexistent) +++ tags/1.2.3/src/crosshair.c (revision 8969) @@ -0,0 +1,1664 @@ +/* + * 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 "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_arc_ui.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 */ + + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +static void XORPolygon(pcb_polygon_t *, pcb_coord_t, pcb_coord_t, int); +static void XORDrawElement(pcb_element_t *, pcb_coord_t, pcb_coord_t); +static void XORDrawBuffer(pcb_buffer_t *); +static void XORDrawInsertPointObject(void); +static void XORDrawAttachedArc(pcb_coord_t); +static void XORDrawPinViaDRCOutline(pcb_pin_t * pv,pcb_coord_t clearance); +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 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(pcb_crosshair.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(pcb_crosshair.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(pcb_crosshair.GC, + x2 - (dx / (double)segs), y2 - (dy / (double)segs), + x2, y2); +} + +/* --------------------------------------------------------------------------- + * creates a tmp polygon with coordinates converted to screen system + */ +static void XORPolygon(pcb_polygon_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) { + 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); + } +} + +/*----------------------------------------------------------- + * Draws the outline of an arc + */ +static void XORDrawArc(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(pcb_crosshair.GC, arc->X, arc->Y, arc->Width + wid, arc->Height + wid, arc->StartAngle, arc->Delta); + if (wid > pcb_pixel_slop) { + pcb_gui->draw_arc(pcb_crosshair.GC, arc->X, arc->Y, arc->Width - wid, arc->Height - wid, arc->StartAngle, arc->Delta); + pcb_gui->draw_arc(pcb_crosshair.GC, x1, y1, wid, wid, arc->StartAngle, -180 * SGN(arc->Delta)); + pcb_gui->draw_arc(pcb_crosshair.GC, x2, y2, wid, wid, arc->StartAngle + arc->Delta, 180 * SGN(arc->Delta)); + } +} + +/*----------------------------------------------------------- + * Draws the outline of an attached arc + */ +static 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; + + XORDrawArc(&arc); +} + +/*----------------------------------------------------------- + * Draws the outline of a line + */ +void XORDrawAttachedLine(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, pcb_coord_t thick) +{ + pcb_coord_t dx, dy, ox, oy; + double h; + + dx = x2 - x1; + dy = y2 - y1; + if (dx != 0 || dy != 0) + h = 0.5 * thick / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy)); + else + h = 0.0; + 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 (coord_abs(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, thick / 2, thick / 2, angle - 180, 180); + pcb_gui->draw_arc(pcb_crosshair.GC, x2, y2, thick / 2, thick / 2, angle, 180); + } +} + +/* --------------------------------------------------------------------------- + * 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 + */ +static 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].On) { + pcb_layer_t *layer = &Buffer->Data->Layer[i]; + + PCB_LINE_LOOP(layer); + { +/* + XORDrawAttachedLine(x +line->Point1.X, + y +line->Point1.Y, x +line->Point2.X, + y +line->Point2.Y, line->Thickness); +*/ + pcb_gui->draw_line(pcb_crosshair.GC, x + line->Point1.X, y + line->Point1.Y, x + line->Point2.X, y + line->Point2.Y); + } + PCB_END_LOOP; + PCB_ARC_LOOP(layer); + { + pcb_gui->draw_arc(pcb_crosshair.GC, x + arc->X, y + arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); + } + PCB_END_LOOP; + PCB_TEXT_LOOP(layer); + { + pcb_box_t *box = &text->BoundingBox; + pcb_gui->draw_rect(pcb_crosshair.GC, x + box->X1, y + box->Y1, x + box->X2, y + box->Y2); + } + 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; + } + + /* and the vias */ + if (PCB->ViaOn) + PCB_VIA_LOOP(Buffer->Data); + { + thindraw_moved_pv(via, x, y); + } + PCB_END_LOOP; +} + +/* --------------------------------------------------------------------------- + * draws the rubberband to insert points into polygons/lines/... + */ +static 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 + */ +static void XORDrawMoveOrCopy(void) +{ + pcb_coord_t dx = pcb_crosshair.X - pcb_crosshair.AttachedObject.X, dy = pcb_crosshair.Y - pcb_crosshair.AttachedObject.Y; + + 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_LINE: + { + /* We move a local copy of the line -the real line hasn't moved, + * only the preview. + */ + int moved = 0; + pcb_line_t line; + memcpy(&line, (pcb_line_t *) pcb_crosshair.AttachedObject.Ptr2, sizeof(line)); + + pcb_event(PCB_EVENT_RUBBER_CONSTRAIN_MAIN_LINE, "pp", &line, &moved); + + if (!moved) + { + line.Point1.X += dx; + line.Point1.Y += dy; + line.Point2.X += dx; + line.Point2.Y += dy; + } + + XORDrawAttachedLine(line.Point1.X, line.Point1.Y, + line.Point2.X, line.Point2.Y, line.Thickness); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawAttachedLine(line.Point1.X, line.Point1.Y, + line.Point2.X, line.Point2.Y, + line.Thickness + 2 * (PCB->Bloat + 1) ); + 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); + arc.X += dx; + arc.Y += dy; + + XORDrawArc(&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); + XORDrawArc(&arc); + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.crosshair); + } + break; + } + + case PCB_TYPE_POLYGON: + { + pcb_polygon_t *polygon = (pcb_polygon_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 */ + XORDrawAttachedLine(point1->X, point1->Y, point2.X, point2.Y, line->Thickness); + + /* Draw the DRC outline if it is enabled */ + if (conf_core.editor.show_drc) { + pcb_gui->set_color(pcb_crosshair.GC, conf_core.appearance.color.cross); + XORDrawAttachedLine(point1->X, point1->Y, point2.X, point2.Y,line->Thickness + 2 * (PCB->Bloat + 1) ); + 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_ui_move_or_copy(&pcb_crosshair); + break; + + case PCB_TYPE_POLYGON_POINT: + { + pcb_polygon_t *polygon; + pcb_point_t *point; + pcb_cardinal_t point_idx, prev, next; + + polygon = (pcb_polygon_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_box_t *box = &text->BoundingBox; + pcb_gui->draw_rect(pcb_crosshair.GC, box->X1 + dx, box->Y1 + dy, box->X2 + dx, box->Y2 + 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; + } + + pcb_event(PCB_EVENT_RUBBER_MOVE_DRAW, "cc", 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 + */ +static 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) +{ + switch (conf_core.editor.mode) { + case PCB_MODE_VIA: + { + /* 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); + } + break; + } + + /* the attached line is used by both LINEMODE, PCB_MODE_POLYGON and PCB_MODE_POLYGON_HOLE */ + case PCB_MODE_POLYGON: + case PCB_MODE_POLYGON_HOLE: + /* 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); + } + break; + + case PCB_MODE_ARC: + 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); + } + + } + break; + + case PCB_MODE_LINE: + 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) + XORDrawAttachedLine(pcb_crosshair.AttachedLine.Point1.X, + pcb_crosshair.AttachedLine.Point1.Y, + pcb_crosshair.AttachedLine.Point2.X, + pcb_crosshair.AttachedLine.Point2.Y, 10 ); + } + 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); + } + break; + + case PCB_MODE_PASTE_BUFFER: + XORDrawBuffer(PCB_PASTEBUFFER); + break; + + case PCB_MODE_COPY: + case PCB_MODE_MOVE: + XORDrawMoveOrCopy(); + break; + + case PCB_MODE_INSERT_POINT: + XORDrawInsertPointObject(); + break; + } + + /* 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); + } +} + + +/* -------------------------------------------------------------------------- + * 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->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); +} + +/* --------------------------------------------------------------------------- + * 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); + DrawLine(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); + DrawArc(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 DrawLine() function anyways. + * ATM DrawLine() only calls AddPart() internally, which invalidates + * the area specified by the line's bounding box. + */ + DrawLine(NULL, (pcb_line_t *) obj); + break; + case PCB_TYPE_ARC_POINT: + /* See comment above */ + DrawArc(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->On) + 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; + } + + } + + pcb_event(PCB_EVENT_RUBBER_FIT_CROSSHAIR, "pppp", &pcb_crosshair, &pcb_marked, + &nearest_grid_x, &nearest_grid_y); + + 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 & PCB_TYPE_ELEMENT) { + pcb_element_t *el = (pcb_element_t *) ptr1; + check_snap_object(&snap_data, el->MarkX, el->MarkY, 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); + } + + 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); + + /* 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) { + pcb_pin_t *pin = (pcb_pin_t *) ptr2; + check_snap_object(&snap_data, pin->X, pin->Y, pcb_true); + } + + 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); + } + + 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, &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); + } + + /* + * 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_POLYGON_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.3/src/crosshair.h =================================================================== --- tags/1.2.3/src/crosshair.h (nonexistent) +++ tags/1.2.3/src/crosshair.h (revision 8969) @@ -0,0 +1,129 @@ +/* + * 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 + * + */ + +/* prototypes for crosshair routines */ + +#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_polygon_t AttachedPolygon; + 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; + + /* 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); + +#endif Index: tags/1.2.3/src/data.c =================================================================== --- tags/1.2.3/src/data.c (nonexistent) +++ tags/1.2.3/src/data.c (revision 8969) @@ -0,0 +1,338 @@ +/* + * 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 + * + */ + +/* just defines common identifiers + */ +#include "config.h" + +#include "board.h" +#include "data.h" +#include "rtree.h" +#include "list_common.h" +#include "obj_all.h" +#include "layer_it.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(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_elements(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(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_all(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_via_cb_t vcb + ) +{ + pcb_loop_layers(ctx, lacb, lcb, acb, tcb, pocb); + pcb_loop_elements(ctx, ecb, elcb, eacb, etcb, epicb, epacb); + pcb_loop_vias(ctx, vcb); +} + +/* --------------------------------------------------------------------------- + * free memory used by data struct + */ +void pcb_data_free(pcb_data_t * data) +{ + pcb_layer_t *layer; + int i; + + if (data == NULL) + return; + + 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; + 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++) { + pcb_attribute_free(&layer->Attributes); + PCB_TEXT_LOOP(layer); + { + free(text->TextString); + } + PCB_END_LOOP; + if (layer->Name) + free((char*)layer->Name); + 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_polygon_t, pcb_poly_free); + 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 (data->element_tree) + pcb_r_destroy_tree(&data->element_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->rat_tree) + pcb_r_destroy_tree(&data->rat_tree); + /* 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) +{ + /* FIX ME: use r_search to do this much faster */ + + /* 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); + { + out->X1 = MIN(out->X1, via->X - via->Thickness / 2); + out->Y1 = MIN(out->Y1, via->Y - via->Thickness / 2); + out->X2 = MAX(out->X2, via->X + via->Thickness / 2); + out->Y2 = MAX(out->Y2, via->Y + via->Thickness / 2); + } + PCB_END_LOOP; + PCB_ELEMENT_LOOP(Data); + { + out->X1 = MIN(out->X1, element->BoundingBox.X1); + out->Y1 = MIN(out->Y1, element->BoundingBox.Y1); + out->X2 = MAX(out->X2, element->BoundingBox.X2); + out->Y2 = MAX(out->Y2, element->BoundingBox.Y2); + { + pcb_text_t *text = &PCB_ELEM_TEXT_REFDES(element); + out->X1 = MIN(out->X1, text->BoundingBox.X1); + out->Y1 = MIN(out->Y1, text->BoundingBox.Y1); + out->X2 = MAX(out->X2, text->BoundingBox.X2); + out->Y2 = MAX(out->Y2, text->BoundingBox.Y2); + }; + } + PCB_END_LOOP; + PCB_LINE_ALL_LOOP(Data); + { + out->X1 = MIN(out->X1, line->Point1.X - line->Thickness / 2); + out->Y1 = MIN(out->Y1, line->Point1.Y - line->Thickness / 2); + out->X1 = MIN(out->X1, line->Point2.X - line->Thickness / 2); + out->Y1 = MIN(out->Y1, line->Point2.Y - line->Thickness / 2); + out->X2 = MAX(out->X2, line->Point1.X + line->Thickness / 2); + out->Y2 = MAX(out->Y2, line->Point1.Y + line->Thickness / 2); + out->X2 = MAX(out->X2, line->Point2.X + line->Thickness / 2); + out->Y2 = MAX(out->Y2, line->Point2.Y + line->Thickness / 2); + } + PCB_ENDALL_LOOP; + PCB_ARC_ALL_LOOP(Data); + { + out->X1 = MIN(out->X1, arc->BoundingBox.X1); + out->Y1 = MIN(out->Y1, arc->BoundingBox.Y1); + out->X2 = MAX(out->X2, arc->BoundingBox.X2); + out->Y2 = MAX(out->Y2, arc->BoundingBox.Y2); + } + PCB_ENDALL_LOOP; + PCB_TEXT_ALL_LOOP(Data); + { + out->X1 = MIN(out->X1, text->BoundingBox.X1); + out->Y1 = MIN(out->Y1, text->BoundingBox.Y1); + out->X2 = MAX(out->X2, text->BoundingBox.X2); + out->Y2 = MAX(out->Y2, text->BoundingBox.Y2); + } + PCB_ENDALL_LOOP; + PCB_POLY_ALL_LOOP(Data); + { + out->X1 = MIN(out->X1, polygon->BoundingBox.X1); + out->Y1 = MIN(out->Y1, polygon->BoundingBox.Y1); + out->X2 = MAX(out->X2, polygon->BoundingBox.X2); + out->Y2 = MAX(out->Y2, polygon->BoundingBox.Y2); + } + PCB_ENDALL_LOOP; + return (pcb_data_is_empty(Data) ? NULL : out); +} + Index: tags/1.2.3/src/data.h =================================================================== --- tags/1.2.3/src/data.h (nonexistent) +++ tags/1.2.3/src/data.h (revision 8969) @@ -0,0 +1,120 @@ +/* + * 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 + * + */ + +/* 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 "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 */ + pinlist_t Via; + elementlist_t Element; +/**/ + pcb_rtree_t *via_tree, *element_tree, *pin_tree, *pad_tree, *name_tree[3], /* for element names */ + *rat_tree; + pcb_board_t *pcb; + pcb_layer_t Layer[PCB_MAX_LAYER]; /* layer TODO: make this dynamic */ + pcb_plug_io_t *loader; + ratlist_t Rat; +}; + +#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_polygon_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); + +/* via callbacks */ +typedef void (*pcb_via_cb_t)(void *ctx, pcb_board_t *pcb, pcb_pin_t *via); + +/* Loop over all layer objects on each layer. Layer is the outer loop. */ +void pcb_loop_layers(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(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 vias. */ +void pcb_loop_vias(void *ctx, pcb_via_cb_t vcb); + +/* Loop over all design objects. (So all the above three in one call.) */ +void pcb_loop_all(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_via_cb_t vcb +); + +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); + +#endif Index: tags/1.2.3/src/default.pcb =================================================================== --- tags/1.2.3/src/default.pcb (nonexistent) +++ tags/1.2.3/src/default.pcb (revision 8969) @@ -0,0 +1,47 @@ +# release: pcb 20110918 + +# To read pcb files, the pcb version (or the git source date) must be >= the file version +FileVersion[20070407] + +PCB["" 600000 500000] + +Grid[2500.0 0 0 1] +Cursor[2500 62500 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") +Layer(1 "component") +( +) +Layer(2 "solder") +( +) +Layer(3 "comp-GND") +( +) +Layer(4 "comp-power") +( +) +Layer(5 "sold-GND") +( +) +Layer(6 "sold-power") +( +) +Layer(7 "signal3") +( +) +Layer(8 "outline") +( +) +Layer(9 "silk") +( +) +Layer(10 "silk") +( +) Index: tags/1.2.3/src/default_font =================================================================== --- tags/1.2.3/src/default_font (nonexistent) +++ tags/1.2.3/src/default_font (revision 8969) @@ -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.3/src/dolists.h =================================================================== --- tags/1.2.3/src/dolists.h (nonexistent) +++ tags/1.2.3/src/dolists.h (revision 8969) @@ -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.3/src/draw.c =================================================================== --- tags/1.2.3/src/draw.c (nonexistent) +++ tags/1.2.3/src/draw.c (revision 8969) @@ -0,0 +1,595 @@ +/* + * 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., 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 + * + */ + + +/* 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_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 Output; /* some widgets ... used for drawing */ + +/* --------------------------------------------------------------------------- + * some local identifiers + */ + +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; + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +static void DrawEverything(const pcb_box_t *); +static void DrawLayerGroup(int, const pcb_box_t *); + +/* 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); + + + +#warning 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); +} + +/* + * 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, draw_hole_callback, &plated, NULL); + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, draw_hole_callback, &plated, NULL); +} + +static void DrawEverything_holes(const pcb_box_t * drawn_area) +{ + int plated, unplated; + pcb_board_count_holes(&plated, &unplated, drawn_area); + + if (plated && pcb_layer_gui_set_vlayer(PCB_VLY_PLATED_DRILL, 0)) { + DrawHoles(pcb_true, pcb_false, drawn_area); + pcb_gui->end_layer(); + } + + if (unplated && pcb_layer_gui_set_vlayer(PCB_VLY_UNPLATED_DRILL, 0)) { + DrawHoles(pcb_false, pcb_true, drawn_area); + 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; + /* 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_bool paste_empty; + + PCB->Data->SILKLAYER.Color = conf_core.appearance.color.element; + PCB->Data->BACKSILKLAYER.Color = conf_core.appearance.color.invisible_objects; + + 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->On && !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); + + /* + * first draw all 'invisible' stuff + */ + if (!conf_core.editor.check_planes && pcb_layer_gui_set_vlayer(PCB_VLY_INVISIBLE, 0)) { + side = PCB_SWAP_IDENT ? PCB_COMPONENT_SIDE : PCB_SOLDER_SIDE; + pcb_draw_silk(PCB_LYT_INVISIBLE_SIDE(), drawn_area); + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, draw_pad_callback, &side, NULL); + 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(group, 0)) { + DrawLayerGroup(group, drawn_area); + pcb_gui->end_layer(); + } + } + + if (conf_core.editor.check_planes && pcb_gui->gui) + return; + + /* Draw pins, pads, vias below silk */ + if (pcb_gui->gui) + pcb_draw_ppv(PCB_SWAP_IDENT ? solder : component, drawn_area); + else if (!pcb_gui->holes_after) + DrawEverything_holes(drawn_area); + + /* Draw the solder mask if turned on */ + gid = pcb_layergrp_get_top_mask(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(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(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(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) + DrawEverything_holes(drawn_area); + + if (pcb_gui->gui) { + /* Draw element Marks */ + if (PCB->PinOn) + pcb_r_search(PCB->Data->element_tree, drawn_area, NULL, draw_element_mark_callback, NULL, NULL); + /* Draw rat lines on top */ + if (pcb_layer_gui_set_vlayer(PCB_VLY_RATS, 0)) { + pcb_draw_rats(drawn_area); + pcb_gui->end_layer(); + } + } + + paste_empty = pcb_layer_is_paste_empty(PCB, PCB_COMPONENT_SIDE); + gid = pcb_layergrp_get_top_paste(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(gid, paste_empty))) { + pcb_draw_paste(PCB_COMPONENT_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + paste_empty = pcb_layer_is_paste_empty(PCB, PCB_SOLDER_SIDE); + gid = pcb_layergrp_get_bottom_paste(); + if ((gid >= 0) && (pcb_layer_gui_set_glayer(gid, paste_empty))) { + pcb_draw_paste(PCB_SOLDER_SIDE, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB_VLY_TOP_ASSY, 0)) { + pcb_draw_assembly(PCB_LYT_TOP, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB_VLY_BOTTOM_ASSY, 0)) { + pcb_draw_assembly(PCB_LYT_BOTTOM, drawn_area); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB_VLY_FAB, 0)) { + pcb_stub_draw_fab(Output.fgGC); + pcb_gui->end_layer(); + } + + if (pcb_layer_gui_set_vlayer(PCB_VLY_CSECT, 0)) { + pcb_stub_draw_csect(Output.fgGC); + pcb_gui->end_layer(); + } + + /* find the first ui layer in use */ + first = NULL; + for(i = 0; i < vtlayer_len(&pcb_uilayer); i++) { + if (pcb_uilayer.array[i].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)) { + for(i = 0; i < vtlayer_len(&pcb_uilayer); i++) + if ((pcb_uilayer.array[i].cookie != NULL) && (pcb_uilayer.array[i].On)) + pcb_draw_layer(pcb_uilayer.array+i, drawn_area); + pcb_gui->end_layer(); + } + +} + +/* --------------------------------------------------------------------------- + * 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, draw_pin_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, draw_pad_callback, &side, NULL); + } + + if (gflg & PCB_LYT_BOTTOM) { + side = PCB_SOLDER_SIDE; + pcb_r_search(PCB->Data->pad_tree, drawn_area, NULL, draw_pad_callback, &side, NULL); + } + } + + /* draw vias */ + if (PCB->ViaOn || !pcb_gui->gui) { + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, draw_via_callback, NULL, NULL); + pcb_r_search(PCB->Data->via_tree, drawn_area, NULL, draw_hole_callback, NULL, NULL); + } + if (PCB->PinOn || pcb_draw_doing_assy) + pcb_r_search(PCB->Data->pin_tree, drawn_area, NULL, draw_hole_callback, NULL, NULL); +} + +#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; + pcb_layer_id_t lid; + 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; + + + /* print the non-clearing polys */ + pcb_r_search(Layer->polygon_tree, screen, NULL, draw_poly_callback, &info, NULL); + + if (conf_core.editor.check_planes) + return; + + /* draw all visible lines this layer */ + pcb_r_search(Layer->line_tree, screen, NULL, draw_line_callback, Layer, NULL); + + /* draw the layer arcs on screen */ + pcb_r_search(Layer->arc_tree, screen, NULL, draw_arc_callback, Layer, NULL); + + /* draw the layer text on screen */ + pcb_r_search(Layer->text_tree, screen, NULL, draw_text_callback, Layer, NULL); + + lid = pcb_layer_id(PCB->Data, Layer); + if (lid >= 0) + lflg = pcb_layer_flags(PCB, lid); + + /* 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(Output.fgGC, Layer->Color); + pcb_gui->set_line_width(Output.fgGC, PCB->minWid); + pcb_gui->draw_rect(Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight); + } +} + +/* --------------------------------------------------------------------------- + * 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 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); + + 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->On) + pcb_draw_layer(Layer, drawn_area); + } + if (n_entries > 1) + rv = 1; + + if (rv && !pcb_gui->gui) + pcb_draw_ppv(group, drawn_area); +} + +void pcb_erase_obj(int type, void *lptr, void *ptr) +{ + switch (type) { + case PCB_TYPE_VIA: + case PCB_TYPE_PIN: + ErasePin((pcb_pin_t *) ptr); + break; + case PCB_TYPE_TEXT: + case PCB_TYPE_ELEMENT_NAME: + EraseText((pcb_layer_t *) lptr, (pcb_text_t *) ptr); + break; + case PCB_TYPE_POLYGON: + ErasePolygon((pcb_polygon_t *) ptr); + break; + case PCB_TYPE_ELEMENT: + EraseElement((pcb_element_t *) ptr); + break; + case PCB_TYPE_LINE: + case PCB_TYPE_ELEMENT_LINE: + case PCB_TYPE_RATLINE: + EraseLine((pcb_line_t *) ptr); + break; + case PCB_TYPE_PAD: + ErasePad((pcb_pad_t *) ptr); + break; + case PCB_TYPE_ARC: + case PCB_TYPE_ELEMENT_ARC: + EraseArc((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(int type, void *ptr1, void *ptr2) +{ + switch (type) { + case PCB_TYPE_VIA: + if (PCB->ViaOn) + DrawVia((pcb_pin_t *) ptr2); + break; + case PCB_TYPE_LINE: + if (((pcb_layer_t *) ptr1)->On) + DrawLine((pcb_layer_t *) ptr1, (pcb_line_t *) ptr2); + break; + case PCB_TYPE_ARC: + if (((pcb_layer_t *) ptr1)->On) + DrawArc((pcb_layer_t *) ptr1, (pcb_arc_t *) ptr2); + break; + case PCB_TYPE_TEXT: + if (((pcb_layer_t *) ptr1)->On) + DrawText((pcb_layer_t *) ptr1, (pcb_text_t *) ptr2); + break; + case PCB_TYPE_POLYGON: + if (((pcb_layer_t *) ptr1)->On) + DrawPolygon((pcb_layer_t *) ptr1, (pcb_polygon_t *) ptr2); + break; + case PCB_TYPE_ELEMENT: + if (pcb_silk_on(PCB) && (PCB_FRONT((pcb_element_t *) ptr2) || PCB->InvisibleObjectsOn)) + DrawElement((pcb_element_t *) ptr2); + break; + case PCB_TYPE_RATLINE: + if (PCB->RatOn) + DrawRat((pcb_rat_t *) ptr2); + break; + case PCB_TYPE_PIN: + if (PCB->PinOn) + DrawPin((pcb_pin_t *) ptr2); + break; + case PCB_TYPE_PAD: + if (PCB->PinOn) + DrawPad((pcb_pad_t *) ptr2); + break; + case PCB_TYPE_ELEMENT_NAME: + if (pcb_silk_on(PCB) && (PCB_FRONT((pcb_element_t *) ptr2) || PCB->InvisibleObjectsOn)) + DrawElementName((pcb_element_t *) ptr1); + break; + } +} + +/* --------------------------------------------------------------------------- + * HID drawing callback. + */ + +static pcb_hid_t *expose_begin(pcb_hid_t *hid) +{ + pcb_hid_t *old_gui = pcb_gui; + + pcb_gui = hid; + Output.fgGC = pcb_gui->make_gc(); + Output.bgGC = pcb_gui->make_gc(); + Output.pmGC = pcb_gui->make_gc(); + + hid->set_color(Output.pmGC, "erase"); + hid->set_color(Output.bgGC, "drill"); + return old_gui; +} + +static void expose_end(pcb_hid_t *old_gui) +{ + pcb_gui->destroy_gc(Output.fgGC); + pcb_gui->destroy_gc(Output.bgGC); + pcb_gui->destroy_gc(Output.pmGC); + pcb_gui = old_gui; +} + +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); + + pcb_draw_doing_pinout = pcb_true; + draw_element(ctx->content.elem); + pcb_draw_doing_pinout = pcb_false; + + 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_VLY_CSECT, 0)) || (e->force)) { + pcb_stub_draw_csect(Output.fgGC); + pcb_gui->end_layer(); + } + } + else if (lflg & PCB_LYT_DIALOG) { + if ((pcb_layer_gui_set_vlayer(PCB_VLY_DIALOG, 0)) || (e->force)) { + e->dialog_draw(Output.fgGC, e); + pcb_gui->end_layer(); + } + } + else if ((e->content.layer_id >= 0) && (e->content.layer_id < pcb_max_layer)) + pcb_draw_layer(&(PCB->Data->Layer[e->content.layer_id]), &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); + } +} Index: tags/1.2.3/src/draw.h =================================================================== --- tags/1.2.3/src/draw.h (nonexistent) +++ tags/1.2.3/src/draw.h (revision 8969) @@ -0,0 +1,107 @@ +/* + * 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., 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 + * + */ + +/* prototypes for drawing routines */ + +#ifndef PCB_DRAW_H +#define PCB_DRAW_H + +#include "config.h" +#include "hid.h" + +/* --------------------------------------------------------------------------- + * some useful values of our widgets + */ +typedef struct { /* holds information about output window */ + pcb_hid_gc_t bgGC, /* background and foreground; */ + fgGC, /* changed from some routines */ + pmGC; /* depth 1 pixmap GC to store clip */ +} pcb_output_t; + +extern pcb_output_t Output; + +/* 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(void); +void pcb_redraw(void); +void pcb_draw_obj(int, void *, void *); +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); + +/*#define PCB_BBOX_DEBUG*/ + +#ifdef PCB_BBOX_DEBUG +#define PCB_DRAW_BBOX(obj) \ + do { \ + pcb_gui->set_line_width(Output.fgGC, 0); \ + pcb_gui->draw_rect(Output.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 composed of multiple layers */ +int pcb_draw_layer_is_comp(pcb_layer_id_t lay_id); + +#endif Index: tags/1.2.3/src/draw_composite.c =================================================================== --- tags/1.2.3/src/draw_composite.c (nonexistent) +++ tags/1.2.3/src/draw_composite.c (revision 8969) @@ -0,0 +1,175 @@ +/* + * 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., 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 + * + */ + +/* 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_layer_group_t *grp; + const char *color; + + unsigned thin:1; + unsigned invert:1; + unsigned poly_before:1; + unsigned poly_after:1; +} comp_ctx_t; + +static void comp_fill_board(comp_ctx_t *ctx, int mask_type) +{ + /* Skip the mask drawing if the GUI doesn't want this type */ + if ((mask_type == HID_MASK_BEFORE && !ctx->poly_before) || (mask_type == HID_MASK_AFTER && !ctx->poly_after)) + return; + + pcb_gui->use_mask(mask_type); + pcb_gui->set_color(Output.fgGC, ctx->color); + if (ctx->screen == NULL) + pcb_gui->fill_rect(Output.fgGC, 0, 0, ctx->pcb->MaxWidth, ctx->pcb->MaxHeight); + else + pcb_gui->fill_rect(Output.fgGC, ctx->screen->X1, ctx->screen->Y1, ctx->screen->X2, ctx->screen->Y2); +} + +static void comp_start_sub_(comp_ctx_t *ctx) +{ + if (ctx->thin) + pcb_gui->set_color(Output.pmGC, ctx->color); + else + pcb_gui->use_mask(HID_MASK_CLEAR); +} + +static void comp_start_add_(comp_ctx_t *ctx) +{ + if (ctx->thin) + pcb_gui->set_color(Output.pmGC, "erase"); + else + pcb_gui->use_mask(HID_MASK_SET); +} + +static void comp_start_sub(comp_ctx_t *ctx) +{ + if (ctx->thin) + 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) + return; + + if (ctx->invert) + comp_start_sub_(ctx); + else + comp_start_add_(ctx); +} + +static void comp_finish(comp_ctx_t *ctx) +{ + if (ctx->thin) + return; + + pcb_gui->use_mask(HID_MASK_AFTER); + comp_fill_board(ctx, HID_MASK_AFTER); + pcb_gui->use_mask(HID_MASK_OFF); +} + +static void comp_init(comp_ctx_t *ctx, int negative) +{ + if (ctx->thin) + return; + + pcb_gui->use_mask(HID_MASK_INIT); + + if (ctx->invert) + negative = !negative; + + if ((!ctx->thin) && (negative)) { + /* old way of drawing the big poly for the negative */ + comp_fill_board(ctx, HID_MASK_BEFORE); + + if (!pcb_gui->poly_before) { + /* new way */ + pcb_gui->use_mask(HID_MASK_SET); + comp_fill_board(ctx, HID_MASK_SET); + } + } +} + +static void comp_draw_layer(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(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(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->Color; + pcb_hid_gc_t old_fg = Output.fgGC; + Output.fgGC = Output.pmGC; + l->Color = ctx->color; + if (!want_add) + l->Color = "erase"; + if (l->comb & PCB_LYC_AUTO) + draw_auto(ctx, auto_data); + pcb_draw_layer(l, ctx->screen); + l->Color = old_color; + Output.fgGC = old_fg; + } + } + if (!adding) + comp_start_add(ctx); +} + +int pcb_draw_layer_is_comp(pcb_layer_id_t id) +{ + pcb_layer_group_t *g = pcb_get_layergrp(PCB, PCB->Data->Layer[id].grp); + if (g == NULL) return 0; + + /* silk has special rules because the original format/model had 1 (auto+) + silk layer in the layer group */ + if (g->type & PCB_LYT_SILK) + return ((g->len != 1) || + ((PCB->Data->Layer[id].comb & (PCB_LYC_AUTO | PCB_LYC_SUB)) != PCB_LYC_AUTO)); + + return (g->len > 0); +} Index: tags/1.2.3/src/draw_ly_spec.c =================================================================== --- tags/1.2.3/src/draw_ly_spec.c (nonexistent) +++ tags/1.2.3/src/draw_ly_spec.c (revision 8969) @@ -0,0 +1,177 @@ +/* + * 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., 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 + * + */ + +/* 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_draw_paste_auto(*(int *)side, ctx->screen); +} + +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.color = conf_core.appearance.color.paste; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly; + cctx.invert = 0; + cctx.poly_before = pcb_gui->poly_before; + cctx.poly_after = pcb_gui->poly_after; + + + if ((cctx.grp == NULL) || (cctx.grp->len == 0)) /* fallback: no layers -> original code: draw a single auto-add */ + pcb_draw_paste_auto(side, drawn_area); + else { + comp_draw_layer(&cctx, pcb_draw_paste_auto_, &side); + comp_finish(&cctx); + } +} + +/******** mask ********/ +static void pcb_draw_mask_auto(comp_ctx_t *ctx, void *side) +{ + pcb_r_search(PCB->Data->pin_tree, ctx->screen, NULL, clear_pin_callback, NULL, NULL); + pcb_r_search(PCB->Data->via_tree, ctx->screen, NULL, clear_pin_callback, NULL, NULL); + pcb_r_search(PCB->Data->pad_tree, ctx->screen, NULL, clear_pad_callback, side, NULL); +} + +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.color = conf_core.appearance.color.mask; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly; + cctx.invert = pcb_gui->mask_invert; + cctx.poly_before = pcb_gui->poly_before; + cctx.poly_after = pcb_gui->poly_after; + + + 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, draw_element_callback, &side, NULL); + pcb_r_search(PCB->Data->name_tree[PCB_ELEMNAME_IDX_VISIBLE()], ctx->screen, NULL, draw_element_name_callback, &side, NULL); +} + +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_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.color = /*PCB->Data->Layer[lid].Color*/ conf_core.appearance.color.element; + cctx.thin = conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly; + cctx.invert = 0; + cctx.poly_before = pcb_gui->poly_before; + cctx.poly_after = pcb_gui->poly_after; + + if ((cctx.grp == NULL) || (cctx.grp->len < 2) || /* fallback: no layers -> original code: draw auto+manual */ + (((cctx.grp->len == 1)) && ((PCB->Data->Layer[lid].comb & (PCB_LYC_AUTO | PCB_LYC_SUB)) == PCB_LYC_AUTO))) { /* fallback: one positive auto layer -> original code: draw auto+manual */ + pcb_draw_layer(LAYER_PTR(lid), cctx.screen); + pcb_draw_silk_auto(&cctx, &lyt_side); + } + 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) +{ + /* + * lesstif allows positive AND negative drawing in HID_MASK_CLEAR. + * gtk only allows negative drawing. + * using the mask here is to get rat transparency + */ + if (pcb_gui->can_mask_clear_rats) + pcb_gui->use_mask(HID_MASK_CLEAR); + pcb_r_search(PCB->Data->rat_tree, drawn_area, NULL, draw_rat_callback, NULL, NULL); + if (pcb_gui->can_mask_clear_rats) + pcb_gui->use_mask(HID_MASK_OFF); +} + +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(Output.fgGC, 1); + DrawLayerGroup(side_group, drawn_area); + pcb_gui->set_draw_faded(Output.fgGC, 0); + + /* draw package */ + pcb_draw_silk(lyt_side, drawn_area); + pcb_draw_doing_assy = pcb_false; +} Index: tags/1.2.3/src/drc.h =================================================================== --- tags/1.2.3/src/drc.h (nonexistent) +++ tags/1.2.3/src/drc.h (revision 8969) @@ -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.3/src/error.c =================================================================== --- tags/1.2.3/src/error.c (nonexistent) +++ tags/1.2.3/src/error.c (revision 8969) @@ -0,0 +1,139 @@ +/* + * 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., 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 + * + */ + + +/* error and debug functions */ + +#include "config.h" + +#include +#include + +#include "data.h" +#include "error.h" +#include "plug_io.h" +#include "compat_misc.h" +#include "compat_nls.h" +#include "conf_core.h" + +#define utf8_dup_string(a,b) *(a) = pcb_strdup(b) + +/* ---------------------------------------------------------------------- + * some external identifiers + */ + +/* the list is already defined for some OS */ +#if !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__linux__) && !defined(__DragonFly__) +#ifdef USE_SYS_ERRLIST +extern char *sys_errlist[]; /* array of error messages */ +#endif +#endif + + +/* --------------------------------------------------------------------------- + * output of message in a dialog window or log window + */ +void pcb_message(enum pcb_message_level level, const char *Format, ...) +{ + va_list args; + pcb_message_level_t min_level = PCB_MSG_INFO; + + /* TODO(hzeller): do something useful with the level, e.g. color coding. */ + + 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); + vfprintf(stderr, Format, args); + va_end(args); +#endif +} + + +/* --------------------------------------------------------------------------- + * print standard 'open error' + */ +void pcb_open_error_message(const char *Filename) +{ + char *utf8 = NULL; + + utf8_dup_string(&utf8, Filename); + pcb_message(PCB_MSG_ERROR, _("Can't open file\n" " '%s'\nfopen() returned: '%s'\n"), utf8, strerror(errno)); + free(utf8); +} + +/* --------------------------------------------------------------------------- + * print standard 'popen error' + */ +void pcb_popen_error_message(const char *Filename) +{ + char *utf8 = NULL; + + utf8_dup_string(&utf8, Filename); + pcb_message(PCB_MSG_ERROR, _("Can't execute command\n" " '%s'\npopen() returned: '%s'\n"), utf8, strerror(errno)); + free(utf8); +} + +/* --------------------------------------------------------------------------- + * print standard 'opendir' + */ +void pcb_opendir_error_message(const char *DirName) +{ + char *utf8 = NULL; + + utf8_dup_string(&utf8, DirName); + pcb_message(PCB_MSG_ERROR, _("Can't scan directory\n" " '%s'\nopendir() returned: '%s'\n"), utf8, strerror(errno)); + free(utf8); +} + +/* --------------------------------------------------------------------------- + * print standard 'chdir error' + */ +void pcb_chdir_error_message(const char *DirName) +{ + char *utf8 = NULL; + + utf8_dup_string(&utf8, DirName); + pcb_message(PCB_MSG_ERROR, _("Can't change working directory to\n" " '%s'\nchdir() returned: '%s'\n"), utf8, strerror(errno)); + free(utf8); +} Index: tags/1.2.3/src/error.h =================================================================== --- tags/1.2.3/src/error.h (nonexistent) +++ tags/1.2.3/src/error.h (revision 8969) @@ -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., 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 + * + */ + +/* prototypes for error 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; + +void pcb_message(enum pcb_message_level level, const char *Format, ...); +void pcb_open_error_message(const char *); +void pcb_popen_error_message(const char *); +void pcb_opendir_error_message(const char *); +void pcb_chdir_error_message(const char *); +void pcb_trace(const char *Format, ...); + +#endif Index: tags/1.2.3/src/event.c =================================================================== --- tags/1.2.3/src/event.c (nonexistent) +++ tags/1.2.3/src/event.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/event.h =================================================================== --- tags/1.2.3/src/event.h (nonexistent) +++ tags/1.2.3/src/event.h (revision 8969) @@ -0,0 +1,116 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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_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_FIT_CROSSHAIR, /* rubber band: fit crosshair and modify lines to keep orientation */ + 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_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.3/src/file_act.c =================================================================== --- tags/1.2.3/src/file_act.c (nonexistent) +++ tags/1.2.3/src/file_act.c (revision 8969) @@ -0,0 +1,401 @@ +/* + * 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" + +/* ---------------------------------------------------------------- */ +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 (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); + + /* 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_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; + + if ((pcb_search_screen(pcb_crosshair.X, pcb_crosshair.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; +} + + + +pcb_hid_action_t file_action_list[] = { + {"ExecCommand", 0, pcb_act_ExecCommand, + pcb_acth_ExecCommand, pcb_acts_ExecCommand} + , + {"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} + , + {"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.3/src/find.c =================================================================== --- tags/1.2.3/src/find.c (nonexistent) +++ tags/1.2.3/src/find.c (revision 8969) @@ -0,0 +1,186 @@ +/* + * + * 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" + +#undef DEBUG + +/* --------------------------------------------------------------------------- + * some local macros + */ + +#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_polygon_t **)PolygonList[(L)].Data)[(I)]) + +#define PVLIST_ENTRY(I) \ + (((pcb_pin_t **)PVList.Data)[(I)]) + +/* --------------------------------------------------------------------------- + * some local types + * + * 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; + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +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]; +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; + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +static pcb_bool LookupLOConnectionsToPVList(pcb_bool); +static pcb_bool LookupLOConnectionsToLOList(pcb_bool); +static pcb_bool LookupPVConnectionsToLOList(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_polygon_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 IsRatPointOnLineEnd(pcb_point_t *, pcb_line_t *); +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(int, void *, void *, void *); +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.3/src/find.h =================================================================== --- tags/1.2.3/src/find.h (nonexistent) +++ tags/1.2.3/src/find.h (revision 8969) @@ -0,0 +1,96 @@ +/* + * 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 + * + */ + +/* prototypes connection search routines */ + +#ifndef PCB_FIND_H +#define PCB_FIND_H + +#include /* needed to define 'FILE *' */ +#include "config.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; + +/* --------------------------------------------------------------------------- + * some local defines + */ +#define PCB_LOOKUP_FIRST \ + (PCB_TYPE_PIN | PCB_TYPE_PAD) +#define PCB_LOOKUP_MORE \ + (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_RATLINE | PCB_TYPE_POLYGON | PCB_TYPE_ARC) +#define PCB_SILK_TYPE \ + (PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_POLYGON) + +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_polygon_t *, pcb_polygon_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(int, void *, void *, void *, pcb_bool, pcb_bool); +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_polygon_t *); +pcb_bool pcb_is_arc_in_poly(pcb_arc_t *, pcb_polygon_t *); +pcb_bool pcb_is_pad_in_poly(pcb_pad_t *, pcb_polygon_t *); + +/* 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); +pcb_bool pcb_clear_flag_on_all_objs(pcb_bool AndDraw, int flag); + +#endif Index: tags/1.2.3/src/find_act.c =================================================================== --- tags/1.2.3/src/find_act.c (nonexistent) +++ tags/1.2.3/src/find_act.c (revision 8969) @@ -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.3/src/find_clear.c =================================================================== --- tags/1.2.3/src/find_clear.c (nonexistent) +++ tags/1.2.3/src/find_clear.c (revision 8969) @@ -0,0 +1,149 @@ +/* + * 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. + */ + +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(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_CLEAR(flag, via); + if (AndDraw) + DrawVia(via); + 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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_CLEAR(flag, pin); + if (AndDraw) + DrawPin(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(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_CLEAR(flag, pad); + if (AndDraw) + DrawPad(pad); + change = pcb_true; + } + } + PCB_END_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(PCB_TYPE_RATLINE, line, line, line); + PCB_FLAG_CLEAR(flag, line); + if (AndDraw) + DrawRat(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(PCB_TYPE_LINE, layer, line, line); + PCB_FLAG_CLEAR(flag, line); + if (AndDraw) + DrawLine(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(PCB_TYPE_ARC, layer, arc, arc); + PCB_FLAG_CLEAR(flag, arc); + if (AndDraw) + DrawArc(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(PCB_TYPE_POLYGON, layer, polygon, polygon); + PCB_FLAG_CLEAR(flag, polygon); + if (AndDraw) + DrawPolygon(layer, polygon); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + if (change) + pcb_board_set_changed_flag(pcb_true); + return change; +} + +/*! + * \brief Resets all found connections. + */ +pcb_bool pcb_clear_flag_on_all_objs(pcb_bool AndDraw, int flag) +{ + pcb_bool change = pcb_false; + + change = pcb_clear_flag_on_pins_vias_pads(AndDraw, flag) || change; + change = pcb_clear_flag_on_lines_polys(AndDraw, flag) || change; + + return change; +} Index: tags/1.2.3/src/find_deadcode.c =================================================================== --- tags/1.2.3/src/find_deadcode.c (nonexistent) +++ tags/1.2.3/src/find_deadcode.c (revision 8969) @@ -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_polygon_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.3/src/find_debug.c =================================================================== --- tags/1.2.3/src/find_debug.c (nonexistent) +++ tags/1.2.3/src/find_debug.c (revision 8969) @@ -0,0 +1,135 @@ +/* + * + * 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; + + if (!PVList.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); + } +} Index: tags/1.2.3/src/find_drc.c =================================================================== --- tags/1.2.3/src/find_drc.c (nonexistent) +++ tags/1.2.3/src/find_drc.c (revision 8969) @@ -0,0 +1,841 @@ +/* + * + * 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" + +/* 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_POLYGON: + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + 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_POLYGON: + { + pcb_polygon_t *polygon = (pcb_polygon_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_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_polygon_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; + + 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(type, ptr1, ptr2, 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(type, ptr1, ptr2, 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(type, ptr1, ptr2, 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(type, ptr1, ptr2, 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(type, ptr1, ptr2, ptr2); + PCB_FLAG_SET(TheFlag, pin); + message = _("Via 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(PCB_TYPE_POLYGON, layer, polygon, polygon); + PCB_FLAG_SET(PCB_FLAG_FOUND, polygon); + DrawPolygon(layer, polygon); + pcb_draw_obj(type, ptr1, 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; + + 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(PCB_TYPE_LINE, layer, line, line); + PCB_FLAG_SET(TheFlag, line); + DrawLine(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(PCB_TYPE_ARC, layer, arc, arc); + PCB_FLAG_SET(TheFlag, arc); + DrawArc(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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_SET(TheFlag, pin); + DrawPin(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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_SET(TheFlag, pin); + DrawPin(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(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_SET(TheFlag, pad); + DrawPad(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(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_SET(TheFlag, via); + DrawVia(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(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_SET(TheFlag, via); + DrawVia(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; + } + + 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); + DrawLine(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); + DrawElement(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; + } + + + 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(What, ptr1, ptr2, ptr3); + DoIt(pcb_true, pcb_false); + /* ok now the shrunk net has the PCB_FLAG_SELECTED set */ + DumpList(); + TheFlag = PCB_FLAG_FOUND; + ListStart(What, ptr1, ptr2, ptr3); + 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(What, ptr1, ptr2, ptr3); + DoIt(pcb_true, pcb_true); + DumpList(); + ListStart(What, ptr1, ptr2, ptr3); + 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(What, ptr1, ptr2, ptr3); + 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(What, ptr1, ptr2, ptr3); + DoIt(pcb_true, pcb_true); + DumpList(); + TheFlag = PCB_FLAG_FOUND; + ListStart(What, ptr1, ptr2, ptr3); + 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_type, thing_ptr1, thing_ptr2, thing_ptr3); + DoIt(pcb_true, pcb_true); + DumpList(); + drc = pcb_true; + Bloat = PCB->Bloat; + ListStart(What, ptr1, ptr2, ptr3); + } + 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_POLYGON: + 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.3/src/find_geo.c =================================================================== --- tags/1.2.3/src/find_geo.c (nonexistent) +++ tags/1.2.3/src/find_geo.c (revision 8969) @@ -0,0 +1,701 @@ +/* + * + * 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" + +#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 + */ +static pcb_bool IsRatPointOnLineEnd(pcb_point_t *Point, pcb_line_t *Line) +{ + if ((Point->X == Line->Point1.X && Point->Y == Line->Point1.Y) + || (Point->X == Line->Point2.X && Point->Y == Line->Point2.Y)) + return (pcb_true); + return (pcb_false); +} + +static void form_slanted_rectangle(pcb_point_t p[4], pcb_line_t *l) +/* writes vertices of a squared line */ +{ + double dwx = 0, dwy = 0; + if (l->Point1.Y == l->Point2.Y) + dwx = l->Thickness / 2.0; + else if (l->Point1.X == l->Point2.X) + dwy = l->Thickness / 2.0; + else { + pcb_coord_t dX = l->Point2.X - l->Point1.X; + pcb_coord_t dY = l->Point2.Y - l->Point1.Y; + double r = pcb_distance(l->Point1.X, l->Point1.Y, l->Point2.X, l->Point2.Y); + dwx = l->Thickness / 2.0 / r * dX; + dwy = l->Thickness / 2.0 / r * dY; + } + p[0].X = l->Point1.X - dwx + dwy; + p[0].Y = l->Point1.Y - dwy - dwx; + p[1].X = l->Point1.X - dwx - dwy; + p[1].Y = l->Point1.Y - dwy + dwx; + p[2].X = l->Point2.X + dwx - dwy; + p[2].Y = l->Point2.Y + dwy + dwx; + p[3].X = l->Point2.X + dwx + dwy; + p[3].Y = l->Point2.Y + dwy - dwx; +} + +/* --------------------------------------------------------------------------- + * checks if two lines intersect + * from news FAQ: + * + * Let A,B,C,D be 2-space position vectors. Then the directed line + * segments AB & CD are given by: + * + * AB=A+r(B-A), r in [0,1] + * CD=C+s(D-C), s in [0,1] + * + * If AB & CD intersect, then + * + * A+r(B-A)=C+s(D-C), or + * + * XA+r(XB-XA)=XC+s(XD-XC) + * YA+r(YB-YA)=YC+s(YD-YC) for some r,s in [0,1] + * + * Solving the above for r and s yields + * + * (YA-YC)(XD-XC)-(XA-XC)(YD-YC) + * r = ----------------------------- (eqn 1) + * (XB-XA)(YD-YC)-(YB-YA)(XD-XC) + * + * (YA-YC)(XB-XA)-(XA-XC)(YB-YA) + * s = ----------------------------- (eqn 2) + * (XB-XA)(YD-YC)-(YB-YA)(XD-XC) + * + * Let I be the position vector of the intersection point, then + * + * I=A+r(B-A) or + * + * XI=XA+r(XB-XA) + * YI=YA+r(YB-YA) + * + * By examining the values of r & s, you can also determine some + * other limiting conditions: + * + * If 0<=r<=1 & 0<=s<=1, intersection exists + * r<0 or r>1 or s<0 or s>1 line segments do not intersect + * + * If the denominator in eqn 1 is zero, AB & CD are parallel + * If the numerator in eqn 1 is also zero, AB & CD are coincident + * + * If the intersection point of the 2 lines are needed (lines in this + * context mean infinite lines) regardless whether the two line + * segments intersect, then + * + * If r>1, I is located on extension of AB + * If r<0, I is located on extension of BA + * If s>1, I is located on extension of CD + * If s<0, I is located on extension of DC + * + * Also note that the denominators of eqn 1 & 2 are identical. + * + */ +pcb_bool pcb_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), 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), 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_polygon_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_FLAG_TEST(PCB_FLAG_CLEARLINE, 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; +} + +/* --------------------------------------------------------------------------- + * 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_polygon_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_FLAG_TEST(PCB_FLAG_CLEARLINE, 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_polygon_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_polygon_t *P1, pcb_polygon_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); +} Index: tags/1.2.3/src/find_lookup.c =================================================================== --- tags/1.2.3/src/find_lookup.c (nonexistent) +++ tags/1.2.3/src/find_lookup.c (revision 8969) @@ -0,0 +1,1458 @@ +/* + * + * 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" + +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->Element ? PCB_TYPE_PIN : PCB_TYPE_VIA, Pin->Element ? Pin->Element : Pin, Pin, 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_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(PCB_TYPE_PAD, Pad->Element, Pad, 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(PCB_TYPE_LINE, LAYER_PTR(L), (Ptr), (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(PCB_TYPE_ARC, LAYER_PTR(L), (Ptr), (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(PCB_TYPE_RATLINE, (Ptr), (Ptr), (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_polygon_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(PCB_TYPE_POLYGON, LAYER_PTR(L), (Ptr), (Ptr)); + PCB_FLAG_SET(TheFlag, (Ptr)); + make_callback(PCB_TYPE_POLYGON, 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_POLYGON, 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; +} + +/* --------------------------------------------------------------------------- + * 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(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 (linelist_length(&layer->Line)) { + LineList[i].Size = linelist_length(&layer->Line); + LineList[i].Data = (void **) calloc(LineList[i].Size, sizeof(pcb_line_t *)); + } + if (arclist_length(&layer->Arc)) { + ArcList[i].Size = arclist_length(&layer->Arc); + ArcList[i].Data = (void **) calloc(ArcList[i].Size, sizeof(pcb_arc_t *)); + } + if (polylist_length(&layer->Polygon)) { + PolygonList[i].Size = polylist_length(&layer->Polygon); + PolygonList[i].Data = (void **) calloc(PolygonList[i].Size, sizeof(pcb_polygon_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; + /* 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; + /* 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_polygon_t *polygon = (pcb_polygon_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; +} + +/* --------------------------------------------------------------------------- + * 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; + + /* loop over all PVs currently on list */ + while (PVList.Location < PVList.Number) { + /* get pointer to data */ + info.pv = *(PVLIST_ENTRY(PVList.Location)); + EXPAND_BOUNDS(&info.pv); + + /* 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)->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; +} + +/* --------------------------------------------------------------------------- + * 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 'LookupPVConnectionsToLOList()' 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; + + /* Internal connection: if pins in the same element have the same + internal connection group number, they are connected */ + ic = PCB_FLAG_INTCONN_GET(orig_pin); + if ((info.pv.Element != NULL) && (ic > 0)) { + pcb_element_t *e = info.pv.Element; + PCB_PIN_LOOP(e); + { + if ((orig_pin != pin) && (ic == PCB_FLAG_INTCONN_GET(pin))) { + if (!PCB_FLAG_TEST(TheFlag, pin)) + ADD_PV_TO_LIST(pin, PCB_TYPE_PIN, orig_pin, PCB_FCT_INTERNAL); + } + } + PCB_END_LOOP; + } + + + 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_polygon_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 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 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_POLYGON, &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_POLYGON, &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_POLYGON, &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; +} + +/* --------------------------------------------------------------------------- + * searches for new PVs that are connected to NEW LOs on the list + * This routine updates the position counter of the lists too. + */ +static pcb_bool LookupPVConnectionsToLOList(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)->no_drc) + continue; + /* do nothing if there are no PV's */ + if (TotalP + TotalV == 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) { + info.line = *(LINELIST_ENTRY(layer, LineList[layer].Location)); + EXPAND_BOUNDS(&info.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; + LineList[layer].Location++; + } + + /* check all arcs */ + while (ArcList[layer].Location < ArcList[layer].Number) { + info.arc = *(ARCLIST_ENTRY(layer, ArcList[layer].Location)); + EXPAND_BOUNDS(&info.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; + ArcList[layer].Location++; + } + + /* now all polygons */ + info.layer = layer; + while (PolygonList[layer].Location < PolygonList[layer].Number) { + info.polygon = *(POLYGONLIST_ENTRY(layer, PolygonList[layer].Location)); + EXPAND_BOUNDS(&info.polygon); + 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; + 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); + + 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; +} + +/* --------------------------------------------------------------------------- + * 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; + pcb_polygon_t *polygon; + gdl_iterator_t it; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + + 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 */ + polylist_foreach(&(PCB->Data->Layer[layer].Polygon), &it, polygon) { + 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; + } + } + + /* 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) + && IsRatPointOnLineEnd(&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) + && IsRatPointOnLineEnd(&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) { + gdl_iterator_t it; + pcb_polygon_t *polygon; + + polylist_foreach(&(PCB->Data->Layer[layer].Polygon), &it, polygon) { + 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; + } + } + } + + /* 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 LOCtoRat_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) && + ((line->Point1.X == i->Point->X && + line->Point1.Y == i->Point->Y) || (line->Point2.X == i->Point->X && line->Point2.Y == i->Point->Y))) { + 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 PolygonToRat_callback(const pcb_box_t * b, void *cl) +{ + pcb_polygon_t *polygon = (pcb_polygon_t *) b; + struct rat_info *i = (struct rat_info *) cl; + + if (!PCB_FLAG_TEST(TheFlag, polygon) && polygon->Clipped && + (i->Point->X == polygon->Clipped->contours->head.point[0]) && + (i->Point->Y == polygon->Clipped->contours->head.point[1])) { + 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]; + /* handle normal layers rats don't ever touch arcs by definition */ + info.layer = layer; + if (setjmp(info.env) == 0) + r_search_pt(LAYER_PTR(layer)->line_tree, Point, 1, NULL, LOCtoRat_callback, &info, NULL); + else + return pcb_true; + if (setjmp(info.env) == 0) + r_search_pt(LAYER_PTR(layer)->polygon_tree, Point, 1, NULL, PolygonToRat_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_polygon_t *polygon = (pcb_polygon_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 = pcb_layer_get_group(PCB, 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 = PCB_FLAG_INTCONN_GET(Pad); + if ((Pad->Element != NULL) && (ic > 0)) { + pcb_element_t *e = Pad->Element; + pcb_pad_t *orig_pad = Pad; + int tlayer = -1; + +/*fprintf(stderr, "lg===\n");*/ + for (entry = 0; entry < PCB->LayerGroups.grp[LayerGroup].len; entry++) { + pcb_layer_id_t layer; + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; +/*fprintf(stderr, "lg: %d\n", layer);*/ + if (layer == PCB_COMPONENT_SIDE) + tlayer = PCB_COMPONENT_SIDE; + else if (layer == PCB_SOLDER_SIDE) + tlayer = PCB_SOLDER_SIDE; + } + +/*fprintf(stderr, "tlayer=%d\n", tlayer);*/ + + if (tlayer >= 0) { + PCB_PAD_LOOP(e); + { + if ((orig_pad != pad) && (ic == PCB_FLAG_INTCONN_GET(pad))) { + int padlayer = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad) ? PCB_SOLDER_SIDE : PCB_COMPONENT_SIDE; +/*fprintf(stderr, "layergroup1: %d {%d %d %d} %d \n", tlayer, PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pad), PCB_SOLDER_SIDE, PCB_COMPONENT_SIDE, padlayer);*/ + if ((!PCB_FLAG_TEST(TheFlag, pad)) && (tlayer != padlayer)) { +/*fprintf(stderr, "layergroup2\n");*/ + ADD_PAD_TO_LIST(padlayer, pad, PCB_TYPE_PAD, orig_pad, PCB_FCT_INTERNAL); + if (LookupLOConnectionsToPad(pad, LayerGroup)) + retv = pcb_true; + } + } + } + PCB_END_LOOP; + } + } + + + 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_POLYGON, &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_POLYGON, &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_POLYGON, &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->Point1.X == (i->polygon.Clipped->contours->head.point[0]) && + rat->Point1.Y == (i->polygon.Clipped->contours->head.point[1]) && + rat->group1 == i->layer) || + (rat->Point2.X == (i->polygon.Clipped->contours->head.point[0]) && + rat->Point2.Y == (i->polygon.Clipped->contours->head.point[1]) && rat->group2 == i->layer)) + if (ADD_RAT_TO_LIST(rat, PCB_TYPE_POLYGON, &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_polygon_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; + gdl_iterator_t it; + pcb_polygon_t *polygon; + + layer = PCB->LayerGroups.grp[LayerGroup].lid[entry]; + + /* handle normal layers */ + /* check all polygons */ + polylist_foreach(&(PCB->Data->Layer[layer].Polygon), &it, polygon) { + if (!PCB_FLAG_TEST(TheFlag, polygon) + && pcb_is_poly_in_poly(polygon, Polygon) + && ADD_POLYGON_TO_LIST(layer, polygon, PCB_TYPE_POLYGON, Polygon, PCB_FCT_COPPER)) + return pcb_true; + } + + 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.3/src/find_misc.c =================================================================== --- tags/1.2.3/src/find_misc.c (nonexistent) +++ tags/1.2.3/src/find_misc.c (revision 8969) @@ -0,0 +1,472 @@ +/* + * + * 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 + * + */ + +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); + 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->no_drc = pcb_attrib_get(l, "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) || LookupLOConnectionsToLOList(AndRats) || LookupPVConnectionsToLOList(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].On) { + /* draw all new lines */ + position = LineList[layer].DrawLocation; + for (; position < LineList[layer].Number; position++) + DrawLine(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++) + DrawArc(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++) + DrawPolygon(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++) + DrawPad(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) + DrawPin(pv); + } + else if (PCB->ViaOn) + DrawVia(pv); + PVList.DrawLocation++; + } + /* draw the new rat-lines */ + if (PCB->RatOn) { + position = RatList.DrawLocation; + for (; position < RatList.Number; position++) + DrawRat(RATLIST_ENTRY(position)); + RatList.DrawLocation = RatList.Number; + } +} + +/*--------------------------------------------------------------------------- + * add the starting object to the list of found objects + */ +static pcb_bool ListStart(int type, void *ptr1, void *ptr2, void *ptr3) +{ + DumpList(); + switch (type) { + case PCB_TYPE_PIN: + case PCB_TYPE_VIA: + { + if (ADD_PV_TO_LIST((pcb_pin_t *) ptr2, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_TYPE_RATLINE: + { + if (ADD_RAT_TO_LIST((pcb_rat_t *) ptr1, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_TYPE_LINE: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, + (pcb_layer_t *) ptr1); + + if (ADD_LINE_TO_LIST(layer, (pcb_line_t *) ptr2, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_TYPE_ARC: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, (pcb_layer_t *) ptr1); + if (ADD_ARC_TO_LIST(layer, (pcb_arc_t *) ptr2, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_TYPE_POLYGON: + { + pcb_layer_id_t layer = pcb_layer_id(PCB->Data, (pcb_layer_t *) ptr1); + + if (ADD_POLYGON_TO_LIST(layer, (pcb_polygon_t *) ptr2, 0, NULL, PCB_FCT_START)) + return pcb_true; + break; + } + + case PCB_TYPE_PAD: + { + pcb_pad_t *pad = (pcb_pad_t *) ptr2; + 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; + } + } + 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) { + pcb_layer_id_t laynum = pcb_layer_id(PCB->Data, (pcb_layer_t *) ptr1); + + /* don't mess with non-conducting objects! */ + if (!(pcb_layer_flags(PCB, laynum) & PCB_LYT_COPPER) || ((pcb_layer_t *) ptr1)->no_drc) + return; + } + } + else { + name = pcb_connection_name(type, ptr1, 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(type, ptr1, ptr2, ptr3); + 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(type, NULL, ptr1, NULL); + + DoIt(pcb_true, pcb_false); + + pcb_conn_lookup_uninit(); +} + + +/* --------------------------------------------------------------------------- + * find connections for rats nesting + * assumes pcb_conn_lookup_init() has already been done + */ +void pcb_rat_find_hook(int type, void *ptr1, void *ptr2, void *ptr3, pcb_bool undo, pcb_bool AndRats) +{ + User = undo; + DumpList(); + ListStart(type, ptr1, ptr2, ptr3); + DoIt(AndRats, pcb_false); + User = pcb_false; +} + +/* --------------------------------------------------------------------------- + * resets all used flags of pins and vias + */ +pcb_bool pcb_reset_found_pins_vias_pads(pcb_bool AndDraw) +{ + pcb_bool change = pcb_false; + + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(TheFlag, via)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_CLEAR(TheFlag, via); + if (AndDraw) + DrawVia(via); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_ELEMENT_LOOP(PCB->Data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(TheFlag, pin)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_CLEAR(TheFlag, pin); + if (AndDraw) + DrawPin(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(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_CLEAR(TheFlag, pad); + if (AndDraw) + DrawPad(pad); + change = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + if (change) + pcb_board_set_changed_flag(pcb_true); + return change; +} + +/* --------------------------------------------------------------------------- + * resets all used flags of LOs + */ +pcb_bool pcb_reset_found_lines_polys(pcb_bool AndDraw) +{ + pcb_bool change = pcb_false; + + PCB_RAT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(TheFlag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_RATLINE, line, line, line); + PCB_FLAG_CLEAR(TheFlag, line); + if (AndDraw) + DrawRat(line); + change = pcb_true; + } + } + PCB_END_LOOP; + PCB_LINE_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(TheFlag, line)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_LINE, layer, line, line); + PCB_FLAG_CLEAR(TheFlag, line); + if (AndDraw) + DrawLine(layer, line); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_ARC_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(TheFlag, arc)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_ARC, layer, arc, arc); + PCB_FLAG_CLEAR(TheFlag, arc); + if (AndDraw) + DrawArc(layer, arc); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + PCB_POLY_COPPER_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(TheFlag, polygon)) { + if (AndDraw) + pcb_undo_add_obj_to_flag(PCB_TYPE_POLYGON, layer, polygon, polygon); + PCB_FLAG_CLEAR(TheFlag, polygon); + if (AndDraw) + DrawPolygon(layer, polygon); + change = pcb_true; + } + } + PCB_ENDALL_LOOP; + 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; + + 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.3/src/find_print.c =================================================================== --- tags/1.2.3/src/find_print.c (nonexistent) +++ tags/1.2.3/src/find_print.c (revision 8969) @@ -0,0 +1,288 @@ +/* + * + * 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 */ + + 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); + DrawPin(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); + DrawPad(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; + + 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.3/src/flag.c =================================================================== --- tags/1.2.3/src/flag.c (nonexistent) +++ tags/1.2.3/src/flag.c (revision 8969) @@ -0,0 +1,87 @@ +/* + * 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., 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 + * + */ + +#include +#include +#include "config.h" +#include "flag.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; + + if (f1->int_conn_grp != f2->int_conn_grp) + 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.3/src/flag.h =================================================================== --- tags/1.2.3/src/flag.h (nonexistent) +++ tags/1.2.3/src/flag.h (revision 8969) @@ -0,0 +1,240 @@ +/* + * 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., 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 + * + */ + +#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 */ + unsigned char int_conn_grp; + 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. +%end-doc */ +typedef enum { + PCB_FLAG_NO = 0x00000, + PCB_FLAG_PIN = 0x00001, /*!< If set, this object is a pin. This flag is for internal use only. */ + PCB_FLAG_VIA = 0x00002, /*!< Likewise, for vias. */ + PCB_FLAG_FOUND = 0x00004, /*!< If set, this object has been found by @code{FindConnection()}. */ + PCB_FLAG_HOLE = 0x00008, /*!< For pins and vias, this flag means that the pin or via is a hole without a copper annulus. */ + PCB_FLAG_NOPASTE = 0x00008, /*!< Pad should not receive solderpaste. This is to support fiducials */ + PCB_FLAG_RAT = 0x00010, /*!< If set for a line, indicates that this line is a rat line instead of a copper trace. */ + PCB_FLAG_PININPOLY = 0x00010, /*!< For pins and pads, this flag is used internally to indicate that the pin or pad overlaps a polygon on some layer.*/ + PCB_FLAG_CLEARPOLY = 0x00010, /*!< 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. */ + PCB_FLAG_HIDENAME = 0x00010, /*!< For elements, when set the name of the element is hidden. */ + PCB_FLAG_DISPLAYNAME = 0x00020, /*!< For elements, when set the names of pins are shown. */ + PCB_FLAG_CLEARLINE = 0x00020, /*!< For lines and arcs, the line/arc will clear polygons instead of connecting to them. */ + PCB_FLAG_FULLPOLY = 0x00020, /*!< For polygons, the full polygon is drawn (i.e. all parts instead of only the biggest one). */ + PCB_FLAG_SELECTED = 0x00040, /*!< Set when the object is selected. */ + PCB_FLAG_ONSOLDER = 0x00080, /*!< For elements and pads, indicates that they are on the solder side. */ + PCB_FLAG_AUTO = 0x00080, /*!< For lines and vias, indicates that these were created by the autorouter. */ + PCB_FLAG_SQUARE = 0x00100, /*!< For pins and pads, indicates a square (vs round) pin/pad. */ + PCB_FLAG_RUBBEREND = 0x00200, /*!< For lines, used internally for rubber band moves: indicates one end already rubber banding. */ + PCB_FLAG_WARN = 0x00200, /*!< For pins, vias, and pads, set to indicate a warning. */ + PCB_FLAG_USETHERMAL = 0x00400, /*!< Obsolete, indicates that pins/vias should be drawn with thermal fingers. */ + 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, /*!< Draw pins and vias as octagons. */ + PCB_FLAG_DRC = 0x01000, /*!< Set for objects that fail DRC: flag like FOUND flag for DRC checking. */ + PCB_FLAG_LOCK = 0x02000, /*!< Set for locked objects. */ + PCB_FLAG_EDGE2 = 0x04000, /*!< 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) */ + PCB_FLAG_VISIT = 0x08000, /*!< marker to avoid re-visiting an object */ + PCB_FLAG_NONETLIST = 0x10000, /* element is not on the netlist and should not interfere with the netlist */ + 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_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. + */ +/* %start-doc pcbfile ~pcbflags +@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 +pcb_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. ++@item 0x800000 ++snap to certain off-grid points. ++@item 0x1000000 ++highlight lines and arcs when the crosshair is on one of their endpoints. +@end table +%end-doc */ + +#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 + + + +/* For passing modified flags to other functions. */ +pcb_flag_t pcb_flag_make(unsigned int); +pcb_flag_t pcb_flag_add(pcb_flag_t, unsigned int); +pcb_flag_t pcb_flag_mask(pcb_flag_t, unsigned int); +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 + + +#define PCB_FLAG_INTCONN_GET(P) ((P)->Flags.int_conn_grp) + +extern int pcb_mem_any_set(unsigned char *, int); +#define PCB_FLAG_THERM_TEST_ANY(P) pcb_mem_any_set((P)->Flags.t, sizeof((P)->Flags.t)) + +#endif Index: tags/1.2.3/src/flag_str.c =================================================================== --- tags/1.2.3/src/flag_str.c (nonexistent) +++ tags/1.2.3/src/flag_str.c (revision 8969) @@ -0,0 +1,580 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 +pcb_flag_bits_t pcb_object_flagbits[] = { + {PCB_FLAG_PIN, N("pin"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_VIA, N("via"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_FOUND, N("found"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_HOLE, N("hole"), PCB_TYPEMASK_PIN}, + {PCB_FLAG_RAT, N("rat"), PCB_TYPE_RATLINE}, + {PCB_FLAG_PININPOLY, N("pininpoly"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD}, + {PCB_FLAG_CLEARPOLY, N("clearpoly"), PCB_TYPE_POLYGON}, + {PCB_FLAG_HIDENAME, N("hidename"), PCB_TYPE_ELEMENT}, + {PCB_FLAG_DISPLAYNAME, N("showname"), PCB_TYPE_ELEMENT}, + {PCB_FLAG_CLEARLINE, N("clearline"), PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_TEXT}, + {PCB_FLAG_SELECTED, N("selected"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_ONSOLDER, N("onsolder"), PCB_TYPE_ELEMENT | PCB_TYPE_PAD | PCB_TYPE_TEXT}, + {PCB_FLAG_AUTO, N("auto"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_SQUARE, N("square"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD}, + {PCB_FLAG_RUBBEREND, N("rubberend"), PCB_TYPE_LINE | PCB_TYPE_ARC}, + {PCB_FLAG_WARN, N("warn"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD}, + {PCB_FLAG_USETHERMAL, N("usetherm"), PCB_TYPEMASK_PIN | PCB_TYPE_LINE | PCB_TYPE_ARC}, + {PCB_FLAG_OCTAGON, N("octagon"), PCB_TYPEMASK_PIN | PCB_TYPE_PAD}, + {PCB_FLAG_DRC, N("drc"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_LOCK, N("lock"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_EDGE2, N("edge2"), PCB_TYPEMASK_ALL}, + {PCB_FLAG_FULLPOLY, N("fullpoly"), PCB_TYPE_POLYGON}, + {PCB_FLAG_NOPASTE, N("nopaste"), PCB_TYPE_PAD}, + {PCB_FLAG_NONETLIST, N("nonetlist"), PCB_TYPEMASK_ALL} +}; +#undef N + +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) +{ + const char *fp, *ep; + int flen; + FlagHolder rv; + int i; + + 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 (flen == 7 && memcmp(fp, "intconn", 7) == 0) { + rv.Flags.int_conn_grp = 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)) +{ + return pcb_strflg_common_s2f(flagstring, error, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits)); +} + + +/* + * 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) +{ + 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 (flags.int_conn_grp > 0) { + len += sizeof("intconn(.)"); + if (flags.q > 9) + len++; + if (flags.q > 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 (flags.int_conn_grp > 0) { + if (bp != buf + 1) + *bp++ = ','; + bp += sprintf(bp, "intconn(%d)", flags.int_conn_grp); + } + + 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) +{ + return pcb_strflg_common_f2s(flags, object_type, pcb_object_flagbits, PCB_ENTRIES(pcb_object_flagbits)); +} + + +#define N(x) x, sizeof(x)-1 +static pcb_flag_bits_t pcb_flagbits[] = { + {PCB_SHOWNUMBERFLAG, N("shownumber"), 1}, + {PCB_LOCALREFFLAG, N("localref"), 1}, + {PCB_CHECKPLANESFLAG, N("checkplanes"), 1}, + {PCB_SHOWPCB_FLAG_DRC, N("showdrc"), 1}, + {PCB_RUBBERBANDFLAG, N("rubberband"), 1}, + {PCB_DESCRIPTIONFLAG, N("description"), 1}, + {PCB_NAMEONPCBFLAG, N("nameonpcb"), 1}, + {PCB_AUTOPCB_FLAG_DRC, N("autodrc"), 1}, + {PCB_ALLDIRECTIONFLAG, N("alldirection"), 1}, + {PCB_SWAPSTARTDIRFLAG, N("swapstartdir"), 1}, + {PCB_UNIQUENAMEFLAG, N("uniquename"), 1}, + {PCB_CLEARNEWFLAG, N("clearnew"), 1}, + {PCB_NEWPCB_FLAG_FULLPOLY, N("newfullpoly"), 1}, + {PCB_SNAPPCB_FLAG_PIN, N("snappin"), 1}, + {PCB_SHOWMASKFLAG, N("showmask"), 1}, + {PCB_THINDRAWFLAG, N("thindraw"), 1}, + {PCB_ORTHOMOVEFLAG, N("orthomove"), 1}, + {PCB_LIVEROUTEFLAG, N("liveroute"), 1}, + {PCB_THINDRAWPOLYFLAG, N("thindrawpoly"), 1}, + {PCB_LOCKNAMESFLAG, N("locknames"), 1}, + {PCB_ONLYNAMESFLAG, N("onlynames"), 1}, + {PCB_HIDENAMESFLAG, N("hidenames"), 1}, + {PCB_ENABLEPCB_FLAG_MINCUT, N("enablemincut"), 1}, +}; +#undef N + + +char *pcb_strflg_board_f2s(pcb_flag_t flags) +{ + return pcb_strflg_common_f2s(flags, PCB_TYPEMASK_ALL, pcb_flagbits, PCB_ENTRIES(pcb_flagbits)); +} + +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)); +} Index: tags/1.2.3/src/flag_str.h =================================================================== --- tags/1.2.3/src/flag_str.h (nonexistent) +++ tags/1.2.3/src/flag_str.h (revision 8969) @@ -0,0 +1,76 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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. */ + int mask; + + /* 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; + +} 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)); + +/* 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); + +/* 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); +char *pcb_strflg_common_f2s(pcb_flag_t flags, int object_type, pcb_flag_bits_t * flagbits, int n_flagbits); + +#endif Index: tags/1.2.3/src/font.c =================================================================== --- tags/1.2.3/src/font.c (nonexistent) +++ tags/1.2.3/src/font.c (revision 8969) @@ -0,0 +1,356 @@ +/* + * 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., 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 + * + */ + +/* 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_polygon_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_polygon_t *pcb_font_new_poly_in_sym(pcb_symbol_t *Symbol, int num_points) +{ + pcb_polygon_t *p = calloc(sizeof(pcb_polygon_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; + + pcb_event(PCB_EVENT_FONT_CHANGED, "i", f->id); + + return f; +} + + +static void pcb_font_free(pcb_font_t *f) +{ + int i; + for (i = 0; i <= PCB_MAX_FONTPOSITION; i++) + free(f->Symbol[i].Line); + 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; +} + +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); + return 0; +} + Index: tags/1.2.3/src/font.h =================================================================== --- tags/1.2.3/src/font.h (nonexistent) +++ tags/1.2.3/src/font.h (revision 8969) @@ -0,0 +1,91 @@ +/* + * 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., 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 + * + */ + +#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_polygon_t *pcb_font_new_poly_in_sym(pcb_symbol_t *Symbol, int num_points); + + +/*** 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); + +/* 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.3/src/font_act.c =================================================================== --- tags/1.2.3/src/font_act.c (nonexistent) +++ tags/1.2.3/src/font_act.c (revision 8969) @@ -0,0 +1,156 @@ +/* + * 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" + + +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; + 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) { + pcb_message(PCB_MSG_ERROR, "LoadFontFrom(): font ID %d is already taken\n", fid); + return 1; + } + } + 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); + 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; + } + + pcb_message(PCB_MSG_INFO, "LoadFontFrom(): new font (ID %d) successfully loaded from file %s\n", fnt->id, 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.3/src/font_internal.c =================================================================== --- tags/1.2.3/src/font_internal.c (nonexistent) +++ tags/1.2.3/src/font_internal.c (revision 8969) @@ -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.3/src/fptr_cast.c =================================================================== --- tags/1.2.3/src/fptr_cast.c (nonexistent) +++ tags/1.2.3/src/fptr_cast.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/fptr_cast.h =================================================================== --- tags/1.2.3/src/fptr_cast.h (nonexistent) +++ tags/1.2.3/src/fptr_cast.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/free_atexit.c =================================================================== --- tags/1.2.3/src/free_atexit.c (nonexistent) +++ tags/1.2.3/src/free_atexit.c (revision 8969) @@ -0,0 +1,110 @@ +/* COPYRIGHT + * + * Copyright (C) 2010 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +#include +#include +#include "config.h" + +/* we need one ID per context - short int with 64k IDs should be enough */ +typedef unsigned int leaky_idx_t; + + +/* This structure should be as big as void *, which should be the natural +bit-width of the architecture. We allocate extra admin space to be as big +as this union, to preserve alignment of pointers returned by malloc(). +NOTE: in the special corner case when leaky_idx_t is wider than void * but +not multiple of it, the alignment will be messed up, potentially causing slower +memory access. */ +typedef union { + leaky_idx_t idx; + void *ptr; +} leaky_admin_t; + +static void **free_list = NULL; +static leaky_idx_t free_size = 0; + + +void *pcb_leaky_malloc(size_t size) +{ + char *new_memory = malloc(size + sizeof(leaky_admin_t)); + + free_list = (void **) realloc(free_list, (free_size + 1) * sizeof(void *)); + free_list[free_size] = new_memory; + *(leaky_idx_t *) new_memory = free_size; + + free_size++; + return new_memory + sizeof(leaky_admin_t); +} + +void *pcb_leaky_calloc(size_t nmemb, size_t size) +{ + size_t size_ = size * nmemb; + void *new_memory = pcb_leaky_malloc(size_); + + memset(new_memory, 0, size_); + return new_memory; +} + +void *pcb_leaky_realloc(void *old_memory_, size_t size) +{ + char *new_memory; + char *old_memory = old_memory_; + leaky_idx_t i; + + if (old_memory == NULL) + return pcb_leaky_malloc(size); + + old_memory -= sizeof(leaky_admin_t); + + i = *(leaky_idx_t *) old_memory; + + new_memory = realloc(old_memory, size + sizeof(leaky_admin_t)); + free_list[i] = new_memory; + + return new_memory + sizeof(leaky_admin_t); +} + +char *pcb_leaky_strdup(const char *src) +{ + int len = strlen(src)+1; + char *res = pcb_leaky_malloc(len); + memcpy(res, src, len); + return res; +} + +void pcb_leaky_uninit(void) +{ + int i; + + for (i = 0; i < free_size; i++) + free(free_list[i]); + + free(free_list); + free_size = 0; +} + +void pcb_leaky_init(void) +{ + atexit(pcb_leaky_uninit); +} Index: tags/1.2.3/src/free_atexit.h =================================================================== --- tags/1.2.3/src/free_atexit.h (nonexistent) +++ tags/1.2.3/src/free_atexit.h (revision 8969) @@ -0,0 +1,38 @@ +/* This tiny library is to assist cleaning up harmless memory leaks caused + by (growing) buffers allocated in static variables in functions. The + library provides pcb_leaky_ prefixed variants of the common allocation + routines. These wrappers will remember all pointers they return and + can free all memory used, at the end of the application. +*/ + +#include + +#ifdef NDEBUG +#define pcb_leaky_init() +#define pcb_leaky_uninit() +#define pcb_leaky_malloc(size) malloc(size) +#define pcb_leaky_calloc(nmemb, size) calloc(nmemb, size) +#define pcb_leaky_realloc(old_memory, size) realloc(old_memory, size) +#define pcb_leaky_strdup(str) strdup(str) +#else + +/* set up atexit() hook - can be avoided if pcb_leaky_uninit() is called by hand */ +void pcb_leaky_init(void); + +/* free all allocations */ +void pcb_leaky_uninit(void); + +/* allocate memory, remember the pointer and free it after exit from the application */ +void *pcb_leaky_malloc(size_t size); + +/* same as leaky_malloc but this one wraps calloc() */ +void *pcb_leaky_calloc(size_t nmemb, size_t size); + +/* reallocate memory, remember the new pointer and free it after exit from the application */ +void *pcb_leaky_realloc(void *old_memory, size_t size); + +/* strdup() using pcb_leaky_malloc() */ +char *pcb_leaky_strdup(const char *src); + + +#endif Index: tags/1.2.3/src/funchash.c =================================================================== --- tags/1.2.3/src/funchash.c (nonexistent) +++ tags/1.2.3/src/funchash.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/funchash.h =================================================================== --- tags/1.2.3/src/funchash.h (nonexistent) +++ tags/1.2.3/src/funchash.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +/* 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); Index: tags/1.2.3/src/funchash_core.h =================================================================== --- tags/1.2.3/src/funchash_core.h (nonexistent) +++ tags/1.2.3/src/funchash_core.h (revision 8969) @@ -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.3/src/funchash_core_list.h =================================================================== --- tags/1.2.3/src/funchash_core_list.h (nonexistent) +++ tags/1.2.3/src/funchash_core_list.h (revision 8969) @@ -0,0 +1,127 @@ +/* + 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(Connection) +action_entry(Convert) +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(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(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.3/src/global_typedefs.h =================================================================== --- tags/1.2.3/src/global_typedefs.h (nonexistent) +++ tags/1.2.3/src/global_typedefs.h (revision 8969) @@ -0,0 +1,60 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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_polygon_s pcb_polygon_t; +typedef struct pcb_pad_s pcb_pad_t; +typedef struct pcb_pin_s pcb_pin_t; +typedef struct pcb_rtree_s pcb_rtree_t; +typedef struct pcb_ratspatch_line_s pcb_ratspatch_line_t; +typedef struct pcb_element_s pcb_element_t; +typedef struct pcb_text_s pcb_text_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.3/src/globalconst.h =================================================================== --- tags/1.2.3/src/globalconst.h (nonexistent) +++ tags/1.2.3/src/globalconst.h (revision 8969) @@ -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., 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 + * + */ + +/* 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.3/src/gui_act.c =================================================================== --- tags/1.2.3/src/gui_act.c (nonexistent) +++ tags/1.2.3/src/gui_act.c (revision 8969) @@ -0,0 +1,1768 @@ +/* + * 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 "error.h" +#include "undo.h" +#include "funchash_core.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 "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_POLYGON + +/* --------------------------------------------------------------------------- */ +/* 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 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 + +%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; +} + +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); + { + EraseElementName(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); + { + DrawElementName(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: + { + void *ptr1, *ptr2, *ptr3; + pcb_coord_t x, y; + pcb_gui->get_coords(_("Click on an element"), &x, &y); + + 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_DISPLAYNAME, pin)) + ErasePinName(pin); + else + DrawPinName(pin); + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, ptr1, pin, pin); + PCB_FLAG_TOGGLE(PCB_FLAG_DISPLAYNAME, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP((pcb_element_t *) ptr1); + { + if (PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, pad)) + ErasePadName(pad); + else + DrawPadName(pad); + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, ptr1, pad, pad); + PCB_FLAG_TOGGLE(PCB_FLAG_DISPLAYNAME, 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_DISPLAYNAME, (pcb_pin_t *) ptr2)) + ErasePinName((pcb_pin_t *) ptr2); + else + DrawPinName((pcb_pin_t *) ptr2); + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, ptr1, ptr2, ptr3); + PCB_FLAG_TOGGLE(PCB_FLAG_DISPLAYNAME, (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_DISPLAYNAME, (pcb_pad_t *) ptr2)) + ErasePadName((pcb_pad_t *) ptr2); + else + DrawPadName((pcb_pad_t *) ptr2); + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, ptr1, ptr2, ptr3); + PCB_FLAG_TOGGLE(PCB_FLAG_DISPLAYNAME, (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_DISPLAYNAME, (pcb_pin_t *) ptr2)) + EraseViaName((pcb_pin_t *) ptr2); + else + DrawViaName((pcb_pin_t *) ptr2); + pcb_undo_add_obj_to_flag(PCB_TYPE_VIA, ptr1, ptr2, ptr3); + PCB_FLAG_TOGGLE(PCB_FLAG_DISPLAYNAME, (pcb_pin_t *) ptr2); + pcb_board_set_changed_flag(pcb_true); + pcb_undo_inc_serial(); + pcb_draw(); + break; + } + 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) { + Note.X = pcb_crosshair.X; + 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); + 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(); + saved_mode = 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) || (conf_core.editor.rubber_band_mode)) + 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(Note.X, l->Point1.X) && close_enough(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(Note.X, l->Point2.X) && close_enough(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(Note.X, ex) && close_enough(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(Note.X, ex) && close_enough(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_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[] = "pcb_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(type, ptr1, ptr2, ptr3); + EraseElementName((pcb_element_t *) ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_HIDENAME, (pcb_element_t *) ptr2); + DrawElementName((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(PCB_TYPE_ELEMENT, element, element, element); + EraseElementName(element); + PCB_FLAG_TOGGLE(PCB_FLAG_HIDENAME, element); + DrawElementName(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_false; + pcb_marked.status = pcb_true; + pcb_marked.X = pcb_crosshair.X; + pcb_marked.Y = pcb_crosshair.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; + pcb_marked.X = pcb_crosshair.X; + pcb_marked.Y = pcb_crosshair.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 != 0) { pcb_custom_route_style.Thick = Thick; conf_set_design("design/line_thickness", "%$mS", Thick); } + if (Clearance != 0) { pcb_custom_route_style.Clearance = Clearance; conf_set_design("design/clearance", "%$mS", Clearance); } + if (Diameter != 0) { pcb_custom_route_style.Diameter = Diameter; conf_set_design("design/via_thickness", "%$mS", Diameter); } + if (Hole != 0) { 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, 0, 0, ((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, 0, 0, ((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_POLYGON: + 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, UNIT_PERCENT}, + {"board", 0, UNIT_PERCENT}, + {"", 0, 0} + }; + pcb_unit_list_t extra_units_y = { + {"grid", 0, 0}, + {"view", 0, UNIT_PERCENT}, + {"board", 0, 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; + + 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(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(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->Attributes, key); + else + ret |= pcb_attribute_put(&ly->Attributes, key, val, 1); + 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"); + + 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_layer_group_t *g = NULL; + + if (CURRENT != NULL) + g = pcb_get_layergrp(PCB, CURRENT->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, 1); + 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"); + + 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_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 (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_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.3/src/heap.c =================================================================== --- tags/1.2.3/src/heap.c (nonexistent) +++ tags/1.2.3/src/heap.c (revision 8969) @@ -0,0 +1,236 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 + +/* --------------------------------------------------------------------------- + * some local prototypes + */ + +/* --------------------------------------------------------------------------- + * some local types + */ +struct heap_element { + pcb_cost_t cost; + void *data; +}; +struct pcb_heap_s { + struct heap_element *element; + int size, max; +}; + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +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.3/src/heap.h =================================================================== --- tags/1.2.3/src/heap.h (nonexistent) +++ tags/1.2.3/src/heap.h (revision 8969) @@ -0,0 +1,62 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* prototypes for heap routines. + */ + +#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.3/src/hid.h =================================================================== --- tags/1.2.3/src/hid.h (nonexistent) +++ tags/1.2.3/src/hid.h (revision 8969) @@ -0,0 +1,621 @@ +#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" + +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_mask_op_s { + HID_MASK_OFF, /* Flushes the buffer and return to non-mask operation. */ + + HID_MASK_BEFORE, /* Polygons being drawn before clears. */ + + HID_MASK_INIT, /* Initialize a new rendering layer for compositing layers */ + HID_MASK_CLEAR, /* negative-draw on the rendering layer */ + HID_MASK_SET, /* positive-draw on the rendering layer */ + + HID_MASK_AFTER /* Polygons being drawn after clears. */ +} pcb_mask_op_t; + +typedef struct hid_s pcb_hid_t; + +/* This is the main HID structure. */ +struct 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, the redraw code will draw polygons before erasing the + clearances. */ + unsigned poly_before:1; + + /* If set, the redraw code will draw polygons after erasing the + clearances. Note that HIDs may set both of these, in which case + polygons will be drawn twice. */ + unsigned poly_after: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; + + /* 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_); + + /* Special note about the "erase" color: To use this color, you must + use this function to tell the HID when you're using it. At the + beginning of a layer redraw cycle (i.e. after set_layer), call + use_mask() to redirect output to a buffer. Draw to the buffer + (using regular HID calls) using regular and "erase" colors. Then + call use_mask(HID_MASK_OFF) to flush the buffer to the HID. If + you use the "erase" color when use_mask is disabled, it simply + draws in the background color. */ + void (*use_mask) (pcb_mask_op_t use_it_); + + /* 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_pcb_polygon) (pcb_hid_gc_t gc_, pcb_polygon_t * poly, const pcb_box_t * clip_box); + void (*thindraw_pcb_polygon) (pcb_hid_gc_t gc_, pcb_polygon_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. */ + pcb_hidval_t(*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); + /* Use this to stop a file watch. */ + 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_); + + /* 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 (*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_element_t *elem; + } content; + + /* for PCB_LYT_DIALOG */ + 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.3/src/hid_actions.c =================================================================== --- tags/1.2.3/src/hid_actions.c (nonexistent) +++ tags/1.2.3/src/hid_actions.c (revision 8969) @@ -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.3/src/hid_actions.h =================================================================== --- tags/1.2.3/src/hid_actions.h (nonexistent) +++ tags/1.2.3/src/hid_actions.h (revision 8969) @@ -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.3/src/hid_attrib.c =================================================================== --- tags/1.2.3/src/hid_attrib.c (nonexistent) +++ tags/1.2.3/src/hid_attrib.c (revision 8969) @@ -0,0 +1,223 @@ +#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_MIXED: + if (a->value) { + *(pcb_hid_attr_val_t *) a->value = a->default_val; + case PCB_HATT_UNIT: + if (a->value) + *(int *) a->value = a->default_val.int_value; + break; + } + 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_MIXED: + a->default_val.real_value = strtod((*argv)[1], &ep); + goto do_enum; + case PCB_HATT_ENUM: + ep = (*argv)[1]; + do_enum: + 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; + } + (*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); + } +} Index: tags/1.2.3/src/hid_attrib.h =================================================================== --- tags/1.2.3/src/hid_attrib.h (nonexistent) +++ tags/1.2.3/src/hid_attrib.h (revision 8969) @@ -0,0 +1,68 @@ +#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. PCB_HATT_MIXED is a real_value followed by an enum, + like 0.5in or 100mm. */ +struct pcb_hid_attr_val_s { + int int_value; + const char *str_value; + double real_value; + pcb_coord_t coord_value; +}; + +typedef enum pcb_hids_e { + PCB_HATT_LABEL, PCB_HATT_INTEGER, PCB_HATT_REAL, PCB_HATT_STRING, + PCB_HATT_BOOL, PCB_HATT_ENUM, PCB_HATT_MIXED, PCB_HATT_PATH, + PCB_HATT_UNIT, PCB_HATT_COORD +} pcb_hids_t; + +struct pcb_hid_attribute_s { + const char *name; + /* If the help_text is this, usage() won't show this option */ +#define ATTR_UNDOCUMENTED ((char *)(1)) + const char *help_text; + pcb_hids_t type; + int min_val, max_val; /* for integer and real */ + pcb_hid_attr_val_t default_val; /* Also actual value for global attributes. */ + 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. Note that a PCB_HATT_MIXED attribute must specify a + pointer to pcb_hid_attr_val_t here, and PCB_HATT_BOOL assumes this is + "char *" so the value should be initialized to zero, and may be + set to non-zero (not always one). */ + 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)(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); +#endif Index: tags/1.2.3/src/hid_cfg.c =================================================================== --- tags/1.2.3/src/hid_cfg.c (nonexistent) +++ tags/1.2.3/src/hid_cfg.c (revision 8969) @@ -0,0 +1,517 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "hid_cfg.h" +#include "error.h" +#include "paths.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; + char *efn; + + pcb_path_resolve(filename, &efn, 0); + + f = fopen(efn, "r"); + if (f == NULL) { + free(efn); + return NULL; + } + doc = lht_dom_init(); + lht_dom_loc_newfile(doc, efn); + + 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, efn, 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); + + free(efn); + 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.3/src/hid_cfg.h =================================================================== --- tags/1.2.3/src/hid_cfg.h (nonexistent) +++ tags/1.2.3/src/hid_cfg.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/hid_cfg_action.c =================================================================== --- tags/1.2.3/src/hid_cfg_action.c (nonexistent) +++ tags/1.2.3/src/hid_cfg_action.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/hid_cfg_action.h =================================================================== --- tags/1.2.3/src/hid_cfg_action.h (nonexistent) +++ tags/1.2.3/src/hid_cfg_action.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/hid_cfg_input.c =================================================================== --- tags/1.2.3/src/hid_cfg_input.c (nonexistent) +++ tags/1.2.3/src/hid_cfg_input.c (revision 8969) @@ -0,0 +1,458 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* 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); } + +/************************** 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)); +} + + +/************************** KEYBOARD ***************************/ +int pcb_hid_cfg_keys_init(pcb_hid_cfg_keys_t *km) +{ + htip_init(&km->keys, keyhash_int, htip_keyeq); + return 0; +} + +int pcb_hid_cfg_keys_uninit(pcb_hid_cfg_keys_t *km) +{ +#warning TODO: recursive free of nodes + htip_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_char, int terminal) +{ + pcb_hid_cfg_keyseq_t *ns; + hid_cfg_keyhash_t addr; + htip_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.hash = 0; + addr.details.mods = mods; + addr.details.key_char = key_char; + + /* already in the tree */ + ns = htip_get(phash, addr.hash); + 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) + htip_init(&ns->seq_next, keyhash_int, htip_keyeq); + htip_set(phash, addr.hash, 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_chars, int arr_len) +{ + const char *curr, *next, *last, *k; + int slen, len; + + slen = 0; + curr = keydesc; + do { + if (slen >= arr_len) + return -1; + while(isspace(*curr)) curr++; + if (*curr == '\0') + break; + next = strchr(curr, ';'); + if (next != NULL) { + len = next - curr; + while(*next == ';') next++; + } + else + len = strlen(curr); + + mods[slen] = parse_mods(curr, &last, len); + + k = strchr(last, '<'); + if (k == NULL) { + pcb_message(PCB_MSG_ERROR, "Missing in the key description: '%s'\n", keydesc); + return -1; + } + len -= k-last; + k++; len--; + if ((strncmp(k, "key>", 4) != 0) && (strncmp(k, "Key>", 4) != 0)) { + pcb_message(PCB_MSG_ERROR, "Missing in the key description\n"); + return -1; + } + k+=4; len-=4; + key_chars[slen] = translate_key(km, k, len); + + if (key_chars[slen] == 0) { + char *s; + s = malloc(len+1); + memcpy(s, k, len); + s[len] = '\0'; + pcb_message(PCB_MSG_ERROR, "Unrecognised key symbol in key description: %s\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_chars[HIDCFG_MAX_KEYSEQ_LEN]; + pcb_hid_cfg_keyseq_t *lasts; + int slen, n; + + slen = parse_keydesc(km, keydesc, mods, key_chars, 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_chars[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_chars[HIDCFG_MAX_KEYSEQ_LEN]; + int slen, n; + + slen = parse_keydesc(km, keydesc, mods, key_chars, 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 (km->key_name(key_chars[n], buff, sizeof(buff)) != 0) + 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_char, pcb_hid_cfg_keyseq_t **seq, int *seq_len) +{ + pcb_hid_cfg_keyseq_t *ns; + hid_cfg_keyhash_t addr; + htip_t *phash = (*seq_len == 0) ? &km->keys : &((seq[(*seq_len)-1])->seq_next); + + addr.hash = 0; + addr.details.mods = mods; + addr.details.key_char = key_char; + + /* already in the tree */ + ns = htip_get(phash, addr.hash); + 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) +{ + if (seq_len < 1) + return -1; + + return pcb_hid_cfg_action(seq[seq_len-1]->action_node); +} Index: tags/1.2.3/src/hid_cfg_input.h =================================================================== --- tags/1.2.3/src/hid_cfg_input.h (nonexistent) +++ tags/1.2.3/src/hid_cfg_input.h (revision 8969) @@ -0,0 +1,144 @@ +#ifndef PCB_HID_CFG_INPUT_H +#define PCB_HID_CFG_INPUT_H + +#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 union hid_cfg_keyhash_u { /* integer hash key */ + unsigned long hash; + struct { + unsigned short int mods; /* of pcb_hid_cfg_mod_t */ + unsigned short int key_char; + } details; +} hid_cfg_keyhash_t; + + +typedef struct pcb_hid_cfg_keyseq_s pcb_hid_cfg_keyseq_t; +struct pcb_hid_cfg_keyseq_s { + 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 */ + + htip_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 { + htip_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. + 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_char, 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. + 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_char, 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.3/src/hid_color.c =================================================================== --- tags/1.2.3/src/hid_color.c (nonexistent) +++ tags/1.2.3/src/hid_color.c (revision 8969) @@ -0,0 +1,41 @@ +#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; +} Index: tags/1.2.3/src/hid_color.h =================================================================== --- tags/1.2.3/src/hid_color.h (nonexistent) +++ tags/1.2.3/src/hid_color.h (revision 8969) @@ -0,0 +1,15 @@ +#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); + +#endif Index: tags/1.2.3/src/hid_draw_helpers.c =================================================================== --- tags/1.2.3/src/hid_draw_helpers.c (nonexistent) +++ tags/1.2.3/src/hid_draw_helpers.c (revision 8969) @@ -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_polygon_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_polygon_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_polygon_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_polygon_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.3/src/hid_draw_helpers.h =================================================================== --- tags/1.2.3/src/hid_draw_helpers.h (nonexistent) +++ tags/1.2.3/src/hid_draw_helpers.h (revision 8969) @@ -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_polygon_t * poly, const pcb_box_t * clip_box); +void pcb_dhlp_thindraw_pcb_polygon(pcb_hid_gc_t gc, pcb_polygon_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.3/src/hid_extents.c =================================================================== --- tags/1.2.3/src/hid_extents.c (nonexistent) +++ tags/1.2.3/src/hid_extents.c (revision 8969) @@ -0,0 +1,161 @@ +#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_use_mask(pcb_mask_op_t use_it) +{ +} + +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.poly_before = 1; + + 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.use_mask = extents_use_mask; + 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.3/src/hid_extents.h =================================================================== --- tags/1.2.3/src/hid_extents.h (nonexistent) +++ tags/1.2.3/src/hid_extents.h (revision 8969) @@ -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.3/src/hid_flags.c =================================================================== --- tags/1.2.3/src/hid_flags.c (nonexistent) +++ tags/1.2.3/src/hid_flags.c (revision 8969) @@ -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].On; + PCB->Data->Layer[i].On = 1; + } +} + +void pcb_hid_restore_layer_ons(int *save_array) +{ + int i; + for (i = 0; i < pcb_max_layer; i++) + PCB->Data->Layer[i].On = save_array[i]; +} Index: tags/1.2.3/src/hid_flags.h =================================================================== --- tags/1.2.3/src/hid_flags.h (nonexistent) +++ tags/1.2.3/src/hid_flags.h (revision 8969) @@ -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.3/src/hid_helper.c =================================================================== --- tags/1.2.3/src/hid_helper.c (nonexistent) +++ tags/1.2.3/src/hid_helper.c (revision 8969) @@ -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., 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 + * + */ + +#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(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[20]; + 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.3/src/hid_helper.h =================================================================== --- tags/1.2.3/src/hid_helper.h (nonexistent) +++ tags/1.2.3/src/hid_helper.h (revision 8969) @@ -0,0 +1,22 @@ +#ifndef PCB_HID_HELPER_H +#define PCB_HID_HELPER_H + +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 TODO 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.3/src/hid_init.c =================================================================== --- tags/1.2.3/src/hid_init.c (nonexistent) +++ tags/1.2.3/src/hid_init.c (revision 8969) @@ -0,0 +1,185 @@ +#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() +{ + pcb_hid_actions_init(); + + /* Setup a "nogui" default HID */ + pcb_gui = pcb_hid_nogui_get_hid(); + +#warning TODO: make this configurable + pcb_plugin_add_dir(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(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)); + + /* 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) { + pcb_plugin_add_dir(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(pcb_concat(conf_core.rc.path.home, PCB_DIR_SEPARATOR_S, DOT_PCB_RND, PCB_DIR_SEPARATOR_S, "plugins", NULL)); + } + pcb_plugin_add_dir(pcb_concat("plugins", PCB_DIR_SEPARATOR_S, HOST, NULL)); + pcb_plugin_add_dir(pcb_concat("plugins", NULL)); +} + +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; + + 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); + 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.3/src/hid_init.h =================================================================== --- tags/1.2.3/src/hid_init.h (nonexistent) +++ tags/1.2.3/src/hid_init.h (revision 8969) @@ -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.3/src/hid_nogui.c =================================================================== --- tags/1.2.3/src/hid_nogui.c (nonexistent) +++ tags/1.2.3/src/hid_nogui.c (revision 8969) @@ -0,0 +1,468 @@ +#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_use_mask(pcb_mask_op_t use_it) +{ + CRASH("use_mask"); +} + +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_polygon_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); + vprintf(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; + } + vprintf(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); + vprintf(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 int nogui_attribute_dialog(pcb_hid_attribute_t * attrs, int n_attrs, pcb_hid_attr_val_t * results, const char *title, const char *descr) +{ + 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->use_mask = nogui_use_mask; + 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->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.3/src/hid_nogui.h =================================================================== --- tags/1.2.3/src/hid_nogui.h (nonexistent) +++ tags/1.2.3/src/hid_nogui.h (revision 8969) @@ -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.3/src/ht_element.c =================================================================== --- tags/1.2.3/src/ht_element.c (nonexistent) +++ tags/1.2.3/src/ht_element.c (revision 8969) @@ -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.3/src/ht_element.h =================================================================== --- tags/1.2.3/src/ht_element.h (nonexistent) +++ tags/1.2.3/src/ht_element.h (revision 8969) @@ -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.3/src/icons/Makefile.am =================================================================== --- tags/1.2.3/src/icons/Makefile.am (nonexistent) +++ tags/1.2.3/src/icons/Makefile.am (revision 8969) @@ -0,0 +1,4 @@ +## $Id$ + +EXTRA_DIST= hand.dat hcurs.dat lcurs.dat lock.dat + Index: tags/1.2.3/src/icons/hand.dat =================================================================== --- tags/1.2.3/src/icons/hand.dat (nonexistent) +++ tags/1.2.3/src/icons/hand.dat (revision 8969) @@ -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.3/src/icons/hcurs.dat =================================================================== --- tags/1.2.3/src/icons/hcurs.dat (nonexistent) +++ tags/1.2.3/src/icons/hcurs.dat (revision 8969) @@ -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.3/src/icons/lcurs.dat =================================================================== --- tags/1.2.3/src/icons/lcurs.dat (nonexistent) +++ tags/1.2.3/src/icons/lcurs.dat (revision 8969) @@ -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.3/src/icons/lock.dat =================================================================== --- tags/1.2.3/src/icons/lock.dat (nonexistent) +++ tags/1.2.3/src/icons/lock.dat (revision 8969) @@ -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.3/src/insert.c =================================================================== --- tags/1.2.3/src/insert.c (nonexistent) +++ tags/1.2.3/src/insert.c (revision 8969) @@ -0,0 +1,156 @@ +/* + * 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 + * + */ + + +/* 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" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t InsertFunctions = { + InsertPointIntoLine, + NULL, + InsertPointIntoPolygon, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + pcb_arc_insert_point, + InsertPointIntoRat, + NULL +}; + +/* --------------------------------------------------------------------------- + * inserts point into objects + */ +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); +} + +/* --------------------------------------------------------------------------- + * adjusts the insert point to make 45 degree lines as necessary + */ +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.3/src/insert.h =================================================================== --- tags/1.2.3/src/insert.h (nonexistent) +++ tags/1.2.3/src/insert.h (revision 8969) @@ -0,0 +1,42 @@ +/* + * 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 + * + */ + +/* prototypes for inserting points into objects */ + +#ifndef PCB_INSERT_H +#define PCB_INSERT_H + +#include "config.h" + +#define PCB_INSERT_TYPES (PCB_TYPE_POLYGON | PCB_TYPE_LINE | PCB_TYPE_ARC | PCB_TYPE_RATLINE) + +/* --------------------------------------------------------------------------- + * prototypes + */ +void *pcb_insert_point_in_object(int, void *, void *, pcb_cardinal_t *, pcb_coord_t, pcb_coord_t, pcb_bool, pcb_bool); +pcb_point_t *pcb_adjust_insert_point(void); + +#endif Index: tags/1.2.3/src/intersect.c =================================================================== --- tags/1.2.3/src/intersect.c (nonexistent) +++ tags/1.2.3/src/intersect.c (revision 8969) @@ -0,0 +1,268 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +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); + +/* --------------------------------------------------------------------------- + * some local types + */ +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.3/src/intersect.h =================================================================== --- tags/1.2.3/src/intersect.h (nonexistent) +++ tags/1.2.3/src/intersect.h (revision 8969) @@ -0,0 +1,43 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* prototypes for 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.3/src/layer.c =================================================================== --- tags/1.2.3/src/layer.c (nonexistent) +++ tags/1.2.3/src/layer.c (revision 8969) @@ -0,0 +1,729 @@ +/* + * 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., 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 + * + */ + +#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" + +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; + +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_empty_(pcb_board_t *pcb, pcb_layer_t *layer) +{ + unsigned int flags; + pcb_layer_id_t lid = pcb_layer_id(pcb->Data, layer); + + if (lid < 0) + return 1; + + flags = pcb_layer_flags(pcb, lid); + + 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; + } + +#warning TODO: check top silk and bottom silk for elements + + /* normal case: a layer is empty if all lists are empty */ + return + (linelist_length(&layer->Line) == 0) && + (arclist_length(&layer->Arc) == 0) && + (polylist_length(&layer->Polygon) == 0) && + (textlist_length(&layer->Text) == 0); +} + +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 >= Data->Layer) && (Layer < (Data->Layer + PCB_MAX_LAYER))) + return Layer - Data->Layer; + + if ((Layer >= pcb_uilayer.array) && (Layer < pcb_uilayer.array + vtlayer_len(&pcb_uilayer))) + return (Layer - pcb_uilayer.array) | PCB_LYT_UI; + + return -1; +} + +#warning layer TODO: with editables this is not enough, check user layers too +pcb_bool pcb_layer_is_paste_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; +} + +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->grp); +} + +#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_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_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(const char *name) +{ + pcb_layer_id_t n; + for (n = 0; n < PCB->Data->LayerN; n++) + if (strcmp(PCB->Data->Layer[n].Name, name) == 0) + return n; + return -1; +} + +void pcb_layers_reset() +{ + 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].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->grp = -1; +} + +pcb_layer_id_t pcb_layer_create(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].On = PCB->Data->Layer[PCB->LayerGroups.grp[grp].lid[0]].On; + } + PCB->Data->Layer[id].grp = grp; + + return id; +} + +int pcb_layer_rename(pcb_layer_id_t layer, const char *lname) +{ + if (PCB->Data->Layer[layer].Name != NULL) + free((char *)PCB->Data->Layer[layer].Name); + PCB->Data->Layer[layer].Name = pcb_strdup(lname); + return 0; +} + +#undef APPEND + +static void swap_one_thermal(int lid1, int lid2, pcb_pin_t * pin) +{ + int was_on_l1 = !!PCB_FLAG_THERM_GET(lid1, pin); + int was_on_l2 = !!PCB_FLAG_THERM_GET(lid2, pin); + + PCB_FLAG_THERM_ASSIGN(lid2, was_on_l1, pin); + PCB_FLAG_THERM_ASSIGN(lid1, was_on_l2, pin); +} + + +static int is_last_top_copper_layer(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(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; +} + +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; +} + +/* Safe move of a layer within a layer array, updaging all fields (list->parents) */ +static void layer_move(pcb_layer_t *dst, pcb_layer_t *src) +{ + pcb_line_t *li; + pcb_text_t *te; + pcb_polygon_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_layer_t *lp, pcb_layer_id_t idx, pcb_layergrp_id_t gid) +{ + memset(lp, 0, sizeof(pcb_layer_t)); + lp->grp = gid; + lp->On = 1; + lp->Name = pcb_strdup("New Layer"); + lp->Color = conf_core.appearance.color.layer[idx]; + lp->SelectedColor = 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; + } + } +} + +int pcb_layer_move(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(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(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_layer_group_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(lp, new_lid, new_in_grp); + else + layer_init(lp, new_lid, PCB->Data->Layer[new_index].grp); + + g = pcb_get_layergrp(PCB, lp->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_layer_group_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].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++) { + 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; +} + +int pcb_layer_swap(pcb_layer_id_t lid1, pcb_layer_id_t lid2) +{ + pcb_layer_t l1tmp, l2tmp; + pcb_layergrp_id_t gid; + + if (lid1 == lid2) + return 0; + + printf("SWAP: %d %d\n", lid1, lid2); + + layer_move(&l1tmp, &PCB->Data->Layer[lid1]); + layer_move(&l2tmp, &PCB->Data->Layer[lid2]); + + layer_move(&PCB->Data->Layer[lid1], &l2tmp); + layer_move(&PCB->Data->Layer[lid2], &l1tmp); + + PCB_VIA_LOOP(PCB->Data); + { + swap_one_thermal(lid1, lid2, via); + } + PCB_END_LOOP; + + PCB_PIN_ALL_LOOP(PCB->Data); + { + swap_one_thermal(lid1, lid2, pin); + } + PCB_ENDALL_LOOP; + + for(gid = 0; gid < pcb_max_group(PCB); gid++) { + pcb_layer_group_t *g = &PCB->LayerGroups.grp[gid]; + int n; + + for(n = 0; n < g->len; n++) { + if (g->lid[n] == lid1) + g->lid[n] = lid2; + else if (g->lid[n] == lid2) + g->lid[n] = lid1; + } + } + + return 0; +} + + + +const char *pcb_layer_name(pcb_layer_id_t id) +{ + if (id < 0) + return NULL; + if (id < PCB->Data->LayerN) + return PCB->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_layer_id_t id) +{ + if ((id >= 0) && (id < PCB->Data->LayerN)) + return &PCB->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; +} + +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_max_layer; 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_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 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(PCB->Data, 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; +} + +static pcb_layer_id_t pcb_layer_get_cached(pcb_layer_id_t *cache, unsigned int loc, unsigned int typ) +{ + pcb_layer_group_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].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(&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(&cache, PCB_LYT_TOP, PCB_LYT_SILK); + assert(id >= 0); + return id; +} Index: tags/1.2.3/src/layer.h =================================================================== --- tags/1.2.3/src/layer.h (nonexistent) +++ tags/1.2.3/src/layer.h (revision 8969) @@ -0,0 +1,249 @@ +/* + * 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., 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 + * + */ + +#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 */ + const char *Name; /* layer name */ + linelist_t Line; + textlist_t Text; + polylist_t Polygon; + arclist_t Arc; + pcb_rtree_t *line_tree, *text_tree, *polygon_tree, *arc_tree; + pcb_bool On; /* visible flag */ + const char *Color; /* color */ + const char *SelectedColor; + pcb_attribute_list_t Attributes; + int no_drc; /* whether to ignore the layer when checking the design rules */ + pcb_layergrp_id_t grp; /* the group this layer is in (cross-reference) */ + + pcb_layer_combining_t comb; /* how to combine this layer with other layers in the group */ + + const char *cookie; /* for UI layers: registration cookie; NULL for unused UI layers */ +}; + + +/* 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; + +pcb_bool pcb_layer_is_paste_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(); + + +/************ 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)]); + +/* Swap two layers in PCB->Data; useful only in writing the old .pcb format, + because silk layers must be the last 2 layers there */ +int pcb_layer_swap(pcb_layer_id_t lid1, pcb_layer_id_t lid2); + +/************ 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_layer_id_t id); + +/* Return the name of a layer (real or virtual) or NULL on error */ +const char *pcb_layer_name(pcb_layer_id_t id); + +/* 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); + +/* call the gui to set a virtual layer or the UI layer group */ +int pcb_layer_gui_set_vlayer(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 is invalid. */ +unsigned int pcb_layer_flags(pcb_board_t *pcb, pcb_layer_id_t layer_idx); + +/* 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_layer_type_t mask, pcb_layer_id_t *res, int res_len); +int pcb_layer_list_any(pcb_layer_type_t mask, pcb_layer_id_t *res, int res_len); + +/* Slow linear search for a layer by name */ +pcb_layer_id_t pcb_layer_by_name(const char *name); + +/**** layer creation (for load/import code) ****/ + +/* Reset layers to the bare minimum (double sided board) */ +void pcb_layers_reset(); + +/* Create a new layer and put it in an existing group (if grp is not -1). */ +pcb_layer_id_t pcb_layer_create(pcb_layergrp_id_t grp, const char *lname); + +/* Rename an existing layer by idx */ +int pcb_layer_rename(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_layer_id_t old_index, pcb_layer_id_t new_index, pcb_layergrp_id_t new_in_grp); + + + + +/* 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)) + +#endif Index: tags/1.2.3/src/layer_grp.c =================================================================== --- tags/1.2.3/src/layer_grp.c (nonexistent) +++ tags/1.2.3/src/layer_grp.c (revision 8969) @@ -0,0 +1,775 @@ +/* + * 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., 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 + * + */ + +#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() \ +do { \ + 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_layer_group_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) +{ + return Layer->grp; +} + +pcb_layer_group_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_layer_group_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->grp; + if (gid >= pcb->LayerGroups.len) + return -1; + + grp = &pcb->LayerGroups.grp[gid]; + + if (layer->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->grp = -1; + NOTIFY(); + 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(); + 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_layer_group_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_empty(pcb, PCB_COMPONENT_SIDE); + if (g->type & PCB_LYT_BOTTOM) + return pcb_layer_is_paste_empty(pcb, PCB_SOLDER_SIDE); + } + + for (i = 0; i < g->len; i++) + if (!pcb_layer_is_empty(pcb, g->lid[i])) + return pcb_false; + return pcb_true; +} + +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_layer_group_t *g = stack->grp + id; + if (g->name != NULL) + free(g->name); + for(n = 0; n < g->len; n++) { + pcb_layer_t *layer = pcb->Data->Layer + g->lid[n]; + layer->grp = -1; + } + memset(g, 0, sizeof(pcb_layer_group_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_layer_group_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_layer_group_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->grp = dst; + } + + memset(s, 0, sizeof(pcb_layer_group_t)); + NOTIFY(); + 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_layer_group_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_layer_group_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(); + return stack->grp+where+1; +} + +static pcb_layer_group_t *pcb_get_grp_new_intern_(pcb_board_t *pcb, int omit_substrate) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + int bl, n; + + if (stack->len+2 >= 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+2, n); + + stack->len += 2; + + 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_layer_group_t *pcb_get_grp_new_intern(pcb_board_t *pcb, int intern_id) +{ + pcb_layer_stack_t *stack = &pcb->LayerGroups; + pcb_layer_group_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(); + } + return g; +} + +pcb_layer_group_t *pcb_get_grp_new_misc(pcb_board_t *pcb) +{ + pcb_layer_group_t *g; + inhibit_notify++; + g = pcb_get_grp_new_intern_(pcb, 1); + inhibit_notify--; + NOTIFY(); + 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->grp > 0) + l->grp += delta; + } + } + } + + remaining = to - from+1; + if (remaining > 0) + memmove(&stk->grp[from + delta], &stk->grp[from], sizeof(pcb_layer_group_t) * remaining); +} + +int pcb_layergrp_index_in_grp(pcb_layer_group_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_layer_group_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(); + 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(stk->grp[gid].lid[n]); + if (l != NULL) { + if (del_layers) { + pcb_layer_move(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->grp = -1; + } + } + } + + pcb_layergrp_free(pcb, gid); + move_grps(pcb, stk, gid+1, stk->len-1, -1); + stk->len--; + NOTIFY(); + 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_layer_group_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_layer_group_t)); + memset(&stk->grp[from], 0, sizeof(pcb_layer_group_t)); + if (to_before < from + 1) { + move_grps(pcb, stk, to_before, from-1, +1); + memcpy(&stk->grp[to_before], &tmp, sizeof(pcb_layer_group_t)); + } + else { + move_grps(pcb, stk, from+1, to_before-1, -1); + memcpy(&stk->grp[to_before-1], &tmp, sizeof(pcb_layer_group_t)); + } + + /* fix up the group id for the layers of the group moved */ + for(n = 0; n < stk->grp[to_before].len; n++) { +#warning TODO: use pcb_get_layer when it becomes pcb-safe +/* pcb_layer_t *l = pcb_get_layer(stk->grp[to_before].lid[n]);*/ + pcb_layer_t *l = &pcb->Data->Layer[stk->grp[to_before].lid[n]]; + if ((l != NULL) && (l->grp > 0)) + l->grp = to_before; + } + + NOTIFY(); + 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_layer_group_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_layer_group_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_layer_group_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_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_layer_group_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_layer_group_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].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_layer_group_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_layer_stack_t *newg) +{ +#warning layer TODO: this still depends on PCB in pcb_layer_create + pcb_layergrp_id_t gid; + for(gid = 0; gid < newg->len; gid++) + if ((newg->grp[gid].type & PCB_LYT_SILK) && (newg->grp[gid].len == 0)) + pcb_layer_create(gid, "silk"); +} + + + +int pcb_layergrp_rename_(pcb_layer_group_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_layer_group_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; +} + + +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_layer_group_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); +} + +/* 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; +} + Index: tags/1.2.3/src/layer_grp.h =================================================================== --- tags/1.2.3/src/layer_grp.h (nonexistent) +++ tags/1.2.3/src/layer_grp.h (revision 8969) @@ -0,0 +1,180 @@ +/* + * 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., 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 + * + */ + +#ifndef PCB_LAYER_GRP_H +#define PCB_LAYER_GRP_H + +typedef struct pcb_layer_group_s pcb_layer_group_t; + +#include "layer.h" + +/* ---------------------------------------------------------------------- + * layer group. A layer group identifies layers which are always switched + * on/off together. + */ + +struct pcb_layer_group_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_layer_group_t grp[PCB_MAX_LAYERGRP]; +}; + +/* Return the layer group for an id, or NULL on error (range check) */ +pcb_layer_group_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_layer_group_t *grp); + + +/* 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_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_layer_group_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_layer_group_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_layer_group_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_layer_group_t *grp, pcb_layer_id_t lid); + + +/* 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_layer_group_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); + + +/********* 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; \ + for (entry = 0; entry < ((pcb_board_t *)(data->pcb))->LayerGroups.grp[(group)].len; entry++) \ + { \ + pcb_layer_t *layer; \ + pcb_layer_id_t number; \ + number = ((pcb_board_t *)(data->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_layer_stack_t *newg); /* make sure we have two silk layers, add them if needed */ +pcb_layer_group_t *pcb_get_grp(pcb_layer_stack_t *stack, pcb_layer_type_t loc, pcb_layer_type_t typ); +pcb_layer_group_t *pcb_get_grp_new_intern(pcb_board_t *pcb, int intern_id); +pcb_layer_group_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_layer_group_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(); + +/* 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); +#endif Index: tags/1.2.3/src/layer_it.h =================================================================== --- tags/1.2.3/src/layer_it.h (nonexistent) +++ tags/1.2.3/src/layer_it.h (revision 8969) @@ -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., 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 + * + */ + +/* 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 */ +static inline PCB_FUNC_UNUSED pcb_layer_id_t pcb_layer_first(pcb_layer_stack_t *stack, pcb_layer_it_t *it, unsigned int exact_mask); +static inline PCB_FUNC_UNUSED 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 */ +static inline PCB_FUNC_UNUSED 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; +}; + +static inline PCB_FUNC_UNUSED 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_layer_group_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 */ + } +} + +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED 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); +} + +static inline PCB_FUNC_UNUSED 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.3/src/layer_ui.c =================================================================== --- tags/1.2.3/src/layer_ui.c (nonexistent) +++ tags/1.2.3/src/layer_ui.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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->cookie == NULL) { + l->cookie = cookie; + goto found; + } + } + + l = vtlayer_alloc_append(&pcb_uilayer, 1); +found:; + l->cookie = cookie; + l->Color = color; + l->Name = name; + l->On = 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->cookie == cookie) { +#warning TODO: free all objects + l->cookie = NULL; + l->Color = l->Name = NULL; + l->On = 0; + pcb_event(PCB_EVENT_LAYERS_CHANGED, NULL); + } + } +} + Index: tags/1.2.3/src/layer_ui.h =================================================================== --- tags/1.2.3/src/layer_ui.h (nonexistent) +++ tags/1.2.3/src/layer_ui.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/layer_vis.c =================================================================== --- tags/1.2.3/src/layer_vis.c (nonexistent) +++ tags/1.2.3/src/layer_vis.c (revision 8969) @@ -0,0 +1,299 @@ +/* + * 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., 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 + * + */ + +/* 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].On; + Layer &= ~(PCB_LYT_UI | PCB_LYT_VIRTUAL); + if (Layer >= vtlayer_len(&pcb_uilayer)) + return 0; + pcb_uilayer.array[Layer].On = On; + changed = 1; + goto done; + } + + if (On < 0) + On = !PCB->Data->Layer[Layer].On; + + 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].On = 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].On = 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].On = pcb_true; + } + PCB->InvisibleObjectsOn = pcb_true; + PCB->PinOn = pcb_true; + PCB->ViaOn = pcb_true; + PCB->RatOn = pcb_true; + + /* Bring the top copper group to the front and make it active. */ + if (pcb_layer_list(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) { + fprintf(stderr, + "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].On; + } + 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) { + fprintf(stderr, "pcb_layervis_restore_stack() layerstack has not" " been saved. cnt = %d\n", SavedStack.cnt); + return; + } + else if (SavedStack.cnt != 1) { + fprintf(stderr, "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].On = 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) +{ + 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].On != *cfg->val.boolean) { + chg = 1; + PCB->Data->Layer[n].On = *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_layer_group_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(g->lid[n]); + if ((l != NULL) && (l->On)) { + 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(g->lid[n]); + pcb_bool_op(l->On, 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_layer_vis_change_all(PCB, PCB_BOOL_SET, PCB_BOOL_PRESERVE); + 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 const char *layer_vis_cookie = "core_layer_vis"; + +void layer_vis_init(void) +{ + conf_native_t *n_mask = conf_get_field("editor/show_mask"); + static conf_hid_callbacks_t cbs_mask; + + layer_vis_conf_id = conf_hid_reg(layer_vis_cookie, NULL); + + if (n_mask != NULL) { + memset(&cbs_mask, 0, sizeof(conf_hid_callbacks_t)); + cbs_mask.val_change_post = layer_vis_chg_mask; + conf_hid_set_cb(n_mask, layer_vis_conf_id, &cbs_mask); + } + + pcb_event_bind(PCB_EVENT_BOARD_CHANGED, layer_vis_grp_defaults, NULL, layer_vis_cookie); +} + +void layer_vis_uninit(void) +{ + pcb_event_unbind_allcookie(layer_vis_cookie); +} Index: tags/1.2.3/src/layer_vis.h =================================================================== --- tags/1.2.3/src/layer_vis.h (nonexistent) +++ tags/1.2.3/src/layer_vis.h (revision 8969) @@ -0,0 +1,58 @@ +/* + * 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., 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 + * + */ + +/* 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 layer_vis_init(void); +void layer_vis_uninit(void); + +/* Sync layer visibility flags to config nodes */ +void layer_vis_sync(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.3/src/library.c =================================================================== --- tags/1.2.3/src/library.c (nonexistent) +++ tags/1.2.3/src/library.c (revision 8969) @@ -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., 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 + * + */ + +#warning 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.3/src/library.h =================================================================== --- tags/1.2.3/src/library.h (nonexistent) +++ tags/1.2.3/src/library.h (revision 8969) @@ -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.3/src/list_common.h =================================================================== --- tags/1.2.3/src/list_common.h (nonexistent) +++ tags/1.2.3/src/list_common.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/list_conf.c =================================================================== --- tags/1.2.3/src/list_conf.c (nonexistent) +++ tags/1.2.3/src/list_conf.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define FROM_CONF_C +#include "conf.h" +#include "list_conf.h" +#include Index: tags/1.2.3/src/list_conf.h =================================================================== --- tags/1.2.3/src/list_conf.h (nonexistent) +++ tags/1.2.3/src/list_conf.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/macro.h =================================================================== --- tags/1.2.3/src/macro.h (nonexistent) +++ tags/1.2.3/src/macro.h (revision 8969) @@ -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., 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 + * + */ + +/* 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.3/src/main.c =================================================================== --- tags/1.2.3/src/main.c (nonexistent) +++ tags/1.2.3/src/main.c (revision 8969) @@ -0,0 +1,595 @@ +/* + * 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., 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 + * + */ + + +/* 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 "board.h" +#include "error.h" +#include "plug_io.h" +#include "buffer.h" +#include "crosshair.h" +#include "compat_lrealpath.h" +#include "free_atexit.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 "vtptr.h" +#include "layer_vis.h" +#include "obj_text.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_hid_uninit(); + pcb_text_uninit(); + 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(); +} + +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, "-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; + vtptr_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 */ + conf_init(); + conf_core_init(); + conf_core_postproc(); /* to get all the paths initialized */ + layer_vis_init(); + + vtptr_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 = vtptr_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(); + + /* This must be called before any other atexit functions + * are registered, as it configures an atexit function to + * clean up and free various items of allocated memory, + * and must be the last last atexit function to run. + */ + pcb_leaky_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(); + + 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 < vtptr_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); + } + } + vtptr_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"); + 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); + + 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"); + pcb_gui->do_export(0); + 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.3/src/main_act.c =================================================================== --- tags/1.2.3/src/main_act.c (nonexistent) +++ tags/1.2.3/src/main_act.c (revision 8969) @@ -0,0 +1,296 @@ +/* + * 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 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., 675 Mass Ave, Cambridge, MA 02139, 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; +} + +/* --------------------------------------------------------------------------- */ + +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} +}; + +PCB_REGISTER_ACTIONS(main_action_list, NULL) Index: tags/1.2.3/src/math_helper.h =================================================================== --- tags/1.2.3/src/math_helper.h (nonexistent) +++ tags/1.2.3/src/math_helper.h (revision 8969) @@ -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., 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 + * + */ + +#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.3/src/misc_util.c =================================================================== --- tags/1.2.3/src/misc_util.c (nonexistent) +++ tags/1.2.3/src/misc_util.c (revision 8969) @@ -0,0 +1,207 @@ +/* + * 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., 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 + * + */ + +/* 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; +} + +/* Get Value returns a numeric value passed from the string and sets the + * pcb_bool variable absolute to false if it leads with a +/- character + */ +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 & 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 & 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; +} + +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; +} + +/* --------------------------------------------------------------------------- + * 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.3/src/misc_util.h =================================================================== --- tags/1.2.3/src/misc_util.h (nonexistent) +++ tags/1.2.3/src/misc_util.h (revision 8969) @@ -0,0 +1,56 @@ +/* + * 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., 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 + * + */ + +/* prototypes for misc routines - 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 { UNIT_PERCENT = 1 }; + +typedef struct { + const char *suffix; + double scale; + enum pcb_unit_flags_e flags; +} pcb_unit_list_t[]; + +double pcb_get_value(const char *, const char *, pcb_bool *, pcb_bool *success); +double pcb_get_value_ex(const char *, const char *, pcb_bool *, pcb_unit_list_t, const char *, pcb_bool *success); +pcb_coord_t pcb_get_num(char **s, const char *default_unit); + + +char *pcb_concat(const char *, ...); /* 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.3/src/move.c =================================================================== --- tags/1.2.3/src/move.c (nonexistent) +++ tags/1.2.3/src/move.c (revision 8969) @@ -0,0 +1,202 @@ +/* + * 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 + * + */ + + +/* 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" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t MoveFunctions = { + MoveLine, + MoveText, + MovePolygon, + MoveVia, + MoveElement, + MoveElementName, + NULL, + NULL, + MoveLinePoint, + MovePolygonPoint, + MoveArc, + NULL, + NULL +}; + +static pcb_opfunc_t MoveToLayerFunctions = { + MoveLineToLayer, + MoveTextToLayer, + MovePolygonToLayer, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MoveArcToLayer, + MoveRatToLayer, + NULL +}; + +/* --------------------------------------------------------------------------- + * moves the object identified by its data pointers and the type + * not we don't bump the undo serial number + */ +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); +} + +/* --------------------------------------------------------------------------- + * moves the object identified by its data pointers and the type + * as well as all attached rubberband lines + */ +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 ctx1; + pcb_opctx_t ctx2; + void *ptr2; + + ctx1.move.pcb = ctx2.move.pcb = PCB; + ctx1.move.dx = ctx2.move.dx = DX; + ctx1.move.dy = ctx2.move.dy = DY; + + pcb_event(PCB_EVENT_RUBBER_MOVE, "ipp", Type, &ctx1, &ctx2); + + if (DX == 0 && DY == 0) + return NULL; + + pcb_draw_inhibit_inc(); + + if (Type == PCB_TYPE_ARC_POINT) { + /* 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; + } + else { + /* If rubberband has adapted movement, move accordingly */ + if (Type == PCB_TYPE_LINE && + (ctx1.move.dx != ctx2.move.dx || ctx1.move.dy != ctx2.move.dy)) { + pcb_line_t *line = (pcb_line_t*) Ptr2; + + /* Move point1 form line */ + pcb_undo_add_obj_to_move(PCB_TYPE_LINE_POINT, + Ptr1, line, &line->Point1, + ctx1.move.dx, ctx1.move.dy); + MoveLinePoint(&ctx1, Ptr1, line, &line->Point1); + + /* Move point2 form line */ + pcb_undo_add_obj_to_move(PCB_TYPE_LINE_POINT, + Ptr1, line, &line->Point2, + ctx2.move.dx, ctx2.move.dy); + ptr2 = MoveLinePoint(&ctx2, Ptr1, line, &line->Point2); + } + /* Otherwise make a normal move */ + else if(Type == PCB_TYPE_LINE_POINT) { + ptr2 = MoveLinePointWithRoute(&ctx1, Ptr1, Ptr2, Ptr3); + } + else { + pcb_undo_add_obj_to_move(Type, Ptr1, Ptr2, Ptr3, DX, DY); + ptr2 = pcb_object_operation(&MoveFunctions, &ctx1, Type, Ptr1, Ptr2, Ptr3); + } + } + pcb_undo_inc_serial(); + + pcb_draw_inhibit_dec(); + pcb_draw(); + + return (ptr2); +} + +/* --------------------------------------------------------------------------- + * moves the object identified by its data pointers and the type + * to a new layer without changing it's position + */ +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); +} + +/* --------------------------------------------------------------------------- + * moves the selected objects to a new layer without changing their + * positions + */ +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, &MoveToLayerFunctions, &ctx, pcb_true, PCB_TYPEMASK_ALL); + /* passing pcb_true to above operation causes Undoserial to auto-increment */ + return (changed); +} Index: tags/1.2.3/src/move.h =================================================================== --- tags/1.2.3/src/move.h (nonexistent) +++ tags/1.2.3/src/move.h (revision 8969) @@ -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., 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 + * + */ + +/* prototypes for move routines */ + +#ifndef PCB_MOVE_H +#define PCB_MOVE_H + +#include "config.h" + +/* --------------------------------------------------------------------------- + * some useful transformation macros and constants + */ +#define PCB_MOVE(xs,ys,deltax,deltay) \ + { \ + ((xs) += (deltax)); \ + ((ys) += (deltay)); \ + } + +#define PCB_MOVE_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | PCB_TYPE_ELEMENT_NAME | \ + PCB_TYPE_POLYGON | PCB_TYPE_POLYGON_POINT | PCB_TYPE_LINE_POINT | PCB_TYPE_ARC | PCB_TYPE_ARC_POINT) +#define PCB_MOVETOLAYER_TYPES \ + (PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_POLYGON | PCB_TYPE_RATLINE | PCB_TYPE_ARC) + + +/* --------------------------------------------------------------------------- + * prototypes + */ +void *pcb_move_obj(int, void *, void *, void *, pcb_coord_t, pcb_coord_t); +void *pcb_move_obj_to_layer(int, void *, void *, void *, pcb_layer_t *, pcb_bool); +void *pcb_move_obj_and_rubberband(int, void *, void *, void *, pcb_coord_t, pcb_coord_t); +pcb_bool pcb_move_selected_objs_to_layer(pcb_layer_t *); + +#endif Index: tags/1.2.3/src/netlist.c =================================================================== --- tags/1.2.3/src/netlist.c (nonexistent) +++ tags/1.2.3/src/netlist.c (revision 8969) @@ -0,0 +1,331 @@ +/* + * 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., 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 + * + */ + +/* 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; + switch (conn.type) { + case PCB_TYPE_PIN: + *x = ((pcb_pin_t *) (conn.ptr2))->X; + *y = ((pcb_pin_t *) (conn.ptr2))->Y; + return 0; + case PCB_TYPE_PAD: + *x = ((pcb_pad_t *) (conn.ptr2))->Point1.X; + *y = ((pcb_pad_t *) (conn.ptr2))->Point1.Y; + return 0; + } + return 1; +} + +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.3/src/netlist.h =================================================================== --- tags/1.2.3/src/netlist.h (nonexistent) +++ tags/1.2.3/src/netlist.h (revision 8969) @@ -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., 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 + * + */ + +#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.3/src/netlist_act.c =================================================================== --- tags/1.2.3/src/netlist_act.c (nonexistent) +++ tags/1.2.3/src/netlist_act.c (revision 8969) @@ -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., 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 + * + */ + +/* 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.3/src/obj_all.h =================================================================== --- tags/1.2.3/src/obj_all.h (nonexistent) +++ tags/1.2.3/src/obj_all.h (revision 8969) @@ -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.3/src/obj_all_list.h =================================================================== --- tags/1.2.3/src/obj_all_list.h (nonexistent) +++ tags/1.2.3/src/obj_all_list.h (revision 8969) @@ -0,0 +1,8 @@ +#include "obj_arc_list.h" +#include "obj_elem_list.h" +#include "obj_line_list.h" +#include "obj_pad_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.3/src/obj_all_op.h =================================================================== --- tags/1.2.3/src/obj_all_op.h (nonexistent) +++ tags/1.2.3/src/obj_all_op.h (revision 8969) @@ -0,0 +1,8 @@ +#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" Index: tags/1.2.3/src/obj_any.c =================================================================== --- tags/1.2.3/src/obj_any.c (nonexistent) +++ tags/1.2.3/src/obj_any.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_any.h =================================================================== --- tags/1.2.3/src/obj_any.h (nonexistent) +++ tags/1.2.3/src/obj_any.h (revision 8969) @@ -0,0 +1,120 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* 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_POLYGON = 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, + + /* 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, + + /* combinations, groups, masks */ + PCB_OBJ_CLASS_MASK= 0xF00000, + PCB_OBJ_CLASS_OBJ = 0x000000, /* anything with common object fields (pcb_any_obj_t) */ + PCB_OBJ_ANY = 0xFFFFFF +} pcb_objtype_t; + +/* 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_DATA /* global objects like via */ +} pcb_parenttype_t; + + +/* class is e.g. PCB_OBJ_CLASS_OBJ */ +#define PCB_OBJ_IS_CLASS(type, class) (((type) & PCB_OBJ_CLASS_MASK) == (class)) + + +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_polygon_t *polygon; + pcb_arc_t *arc; + pcb_rat_t *rat; + pcb_pad_t *pad; + pcb_pin_t *pin; + pcb_pin_t *via; + pcb_element_t *element; + pcb_net_t *net; + pcb_layer_t *layer; + } data; + + pcb_parenttype_t parent_type; + union { + void *any; + pcb_layer_t *layer; + pcb_data_t *data; + pcb_element_t *element; + } 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.3/src/obj_arc.c =================================================================== --- tags/1.2.3/src/obj_arc.c (nonexistent) +++ tags/1.2.3/src/obj_arc.c (revision 8969) @@ -0,0 +1,740 @@ +/* + * 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 + * + */ + +/* 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 "obj_arc.h" +#include "obj_arc_op.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); + 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); + + 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 = Arc->X - Arc->Width * cos(Arc->StartAngle * PCB_M180); + *y = Arc->Y + Arc->Height * sin(Arc->StartAngle * PCB_M180); + } + else { + *x = Arc->X - Arc->Width * cos((Arc->StartAngle + Arc->Delta) * PCB_M180); + *y = Arc->Y + 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); +} + +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); +} + + + +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 *AddArcToBuffer(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)]; + + return (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))); +} + +/* moves an arc to buffer */ +void *MoveArcToBuffer(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); + return (arc); +} + +/* changes the size of an arc */ +void *ChangeArcSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Arc->Thickness + ctx->chgsize.delta; + + 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); + EraseArc(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); + DrawArc(Layer, Arc); + return (Arc); + } + return (NULL); +} + +/* changes the clearance size of an arc */ +void *ChangeArcClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Arc->Clearance + ctx->chgsize.delta; + + 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, MAX(value, PCB->Bloat * 2 + 2)); + if (value != Arc->Clearance) { + pcb_undo_add_obj_to_clear_size(PCB_TYPE_ARC, Layer, Arc, Arc); + EraseArc(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; + if (Arc->Clearance == 0) { + PCB_FLAG_CLEAR(PCB_FLAG_CLEARLINE, Arc); + Arc->Clearance = PCB_MIL_TO_COORD(10); + } + 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); + DrawArc(Layer, Arc); + return (Arc); + } + return (NULL); +} + +/* changes the radius of an arc (is_primary 0=width or 1=height or 2=both) */ +void *ChangeArcRadius(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 = ChangeArcRadius(ctx, Layer, Arc); + ctx->chgsize.is_primary = 1; a1 = ChangeArcRadius(ctx, Layer, Arc); + if ((a0 != NULL) || (a1 != NULL)) + return Arc; + return NULL; + } + + value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : (*dst) + ctx->chgsize.delta; + 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); + EraseArc(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); + DrawArc(Layer, Arc); + return (Arc); + } + return (NULL); +} + +/* changes the angle of an arc (is_primary 0=start or 1=end) */ +void *ChangeArcAngle(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 = ChangeArcAngle(ctx, Layer, Arc); + ctx->chgangle.is_primary = 1; a1 = ChangeArcAngle(ctx, Layer, Arc); + if ((a0 != NULL) || (a1 != NULL)) + return Arc; + return NULL; + } + + value = (ctx->chgangle.absolute) ? ctx->chgangle.absolute : (*dst) + ctx->chgangle.delta; + value = fmod(value, 360.0); + if (value < 0) + value += 360; + + if (value != *dst) { + pcb_undo_add_obj_to_change_angles(PCB_TYPE_ARC, Layer, Arc, Arc); + EraseArc(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); + DrawArc(Layer, Arc); + return (Arc); + } + return (NULL); +} + +/* changes the clearance flag of an arc */ +void *ChangeArcJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Arc)) + return (NULL); + EraseArc(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(PCB_TYPE_ARC, Layer, Arc, 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); + } + DrawArc(Layer, Arc); + return (Arc); +} + +/* sets the clearance flag of an arc */ +void *SetArcJoin(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 ChangeArcJoin(ctx, Layer, Arc); +} + +/* clears the clearance flag of an arc */ +void *ClrArcJoin(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 ChangeArcJoin(ctx, Layer, Arc); +} + +/* copies an arc */ +void *CopyArc(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); + DrawArc(Layer, arc); + pcb_undo_add_obj_to_create(PCB_TYPE_ARC, Layer, arc, arc); + return (arc); +} + +/* moves an arc */ +void *MoveArc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_ARC, Layer, Arc); + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + if (Layer->On) { + EraseArc(Arc); + pcb_arc_move(Arc, ctx->move.dx, ctx->move.dy); + DrawArc(Layer, Arc); + pcb_draw(); + } + else { + pcb_arc_move(Arc, ctx->move.dx, ctx->move.dy); + } + 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 *MoveArcToLayerLowLevel(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); + return arc; +} + + +/* moves an arc between layers */ +void *MoveArcToLayer(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->On) { + DrawArc(Layer, Arc); + pcb_draw(); + } + if (((long int) ctx->move.dst_layer == -1) || 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->On) + EraseArc(Arc); + newone = (pcb_arc_t *) MoveArcToLayerLowLevel(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->On) + DrawArc(ctx->move.dst_layer, newone); + pcb_draw(); + return (newone); +} + +/* destroys an arc from a layer */ +void *DestroyArc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_r_delete_entry(Layer->arc_tree, (pcb_box_t *) Arc); + + pcb_arc_free(Arc); + + return NULL; +} + +/* removes an arc from a layer */ +void *RemoveArc_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + /* erase from screen */ + if (Layer->On) { + EraseArc(Arc); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_ARC, Layer, Arc, Arc); + return NULL; +} + +void *RemoveArcPoint_op(pcb_opctx_t *ctx, pcb_layer_t *l, pcb_arc_t *a, int *end_id) +{ + return RemoveArc_op(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 RemoveArc_op(&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; + } + pcb_box_rotate90(&Arc->BoundingBox, X, Y, 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) +{ + 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_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); +} + +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 *Rotate90Arc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + EraseArc(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); + DrawArc(Layer, Arc); + pcb_draw(); + 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); + + 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; +} + +/*** draw ***/ +void _draw_arc(pcb_arc_t * arc) +{ + if (!arc->Thickness) + return; + + PCB_DRAW_BBOX(arc); + + if (conf_core.editor.thin_draw) + pcb_gui->set_line_width(Output.fgGC, 0); + else + pcb_gui->set_line_width(Output.fgGC, arc->Thickness); + pcb_gui->set_line_cap(Output.fgGC, Trace_Cap); + + pcb_gui->draw_arc(Output.fgGC, arc->X, arc->Y, arc->Width, arc->Height, arc->StartAngle, arc->Delta); +} + +void draw_arc(pcb_layer_t * layer, pcb_arc_t * arc) +{ + 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->SelectedColor; + else + color = conf_core.appearance.color.connected; + } + else + color = layer->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(Output.fgGC, color); + _draw_arc(arc); +} + +pcb_r_dir_t draw_arc_callback(const pcb_box_t * b, void *cl) +{ + draw_arc((pcb_layer_t *) cl, (pcb_arc_t *) b); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases an arc on a layer */ +void EraseArc(pcb_arc_t *Arc) +{ + if (!Arc->Thickness) + return; + pcb_draw_invalidate(Arc); + pcb_flag_erase(&Arc->Flags); +} + +void DrawArc(pcb_layer_t *Layer, pcb_arc_t *Arc) +{ + pcb_draw_invalidate(Arc); +} Index: tags/1.2.3/src/obj_arc.h =================================================================== --- tags/1.2.3/src/obj_arc.h (nonexistent) +++ tags/1.2.3/src/obj_arc.h (revision 8969) @@ -0,0 +1,127 @@ +/* + * 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 + * + */ + +/* 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); +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); +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_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->On) \ + PCB_ARC_LOOP(layer) + +#endif Index: tags/1.2.3/src/obj_arc_draw.h =================================================================== --- tags/1.2.3/src/obj_arc_draw.h (nonexistent) +++ tags/1.2.3/src/obj_arc_draw.h (revision 8969) @@ -0,0 +1,37 @@ +/* + * 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 + * + */ + +/*** Standard draw of arcs ***/ + +/* Include rtree.h for this */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_arc_callback(const pcb_box_t * b, void *cl); +#endif + +void _draw_arc(pcb_arc_t * arc); +void draw_arc(pcb_layer_t * layer, pcb_arc_t * arc); +void EraseArc(pcb_arc_t *Arc); +void DrawArc(pcb_layer_t *Layer, pcb_arc_t *Arc); Index: tags/1.2.3/src/obj_arc_list.c =================================================================== --- tags/1.2.3/src/obj_arc_list.c (nonexistent) +++ tags/1.2.3/src/obj_arc_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_arc_list.h" +#include Index: tags/1.2.3/src/obj_arc_list.h =================================================================== --- tags/1.2.3/src/obj_arc_list.h (nonexistent) +++ tags/1.2.3/src/obj_arc_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_arc_op.h =================================================================== --- tags/1.2.3/src/obj_arc_op.h (nonexistent) +++ tags/1.2.3/src/obj_arc_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on arc ***/ + +#include "operation.h" + +void *AddArcToBuffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *MoveArcToBuffer(pcb_opctx_t *ctx, pcb_layer_t *layer, pcb_arc_t *arc); +void *ChangeArcSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *ChangeArcClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *ChangeArcRadius(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *ChangeArcAngle(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *ChangeArcJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *SetArcJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *ClrArcJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *CopyArc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *MoveArc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *MoveArcToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_arc_t * arc, pcb_layer_t * Destination); +void *MoveArcToLayer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_arc_t * Arc); +void *DestroyArc(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *RemoveArc_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_arc_t *Arc); +void *RemoveArcPoint_op(pcb_opctx_t *ctx, pcb_layer_t *l, pcb_arc_t *a, int *end_id); +void *Rotate90Arc(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.3/src/obj_arc_ui.c =================================================================== --- tags/1.2.3/src/obj_arc_ui.c (nonexistent) +++ tags/1.2.3/src/obj_arc_ui.c (revision 8969) @@ -0,0 +1,139 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_arc_ui.h =================================================================== --- tags/1.2.3/src/obj_arc_ui.h (nonexistent) +++ tags/1.2.3/src/obj_arc_ui.h (revision 8969) @@ -0,0 +1,31 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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); + Index: tags/1.2.3/src/obj_common.c =================================================================== --- tags/1.2.3/src/obj_common.c (nonexistent) +++ tags/1.2.3/src/obj_common.c (revision 8969) @@ -0,0 +1,108 @@ +/* + * 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., 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 + * + */ + +/* functions used to create vias, pins ... */ + +#include "config.h" + +#include "conf_core.h" +#include "global_typedefs.h" +#include "const.h" +#include "error.h" +#include "obj_common.h" +#include "obj_arc_ui.h" + + +/* 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_POLYGON: + case PCB_TYPE_PAD: + case PCB_TYPE_PIN: + case PCB_TYPE_ELEMENT_NAME: + *res = *(pcb_box_t *)Ptr2; + return 0; + case PCB_TYPE_VIA: + case PCB_TYPE_ELEMENT: + *res = *(pcb_box_t *)Ptr1; + return 0; + case PCB_TYPE_POLYGON_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, 0); +} Index: tags/1.2.3/src/obj_common.h =================================================================== --- tags/1.2.3/src/obj_common.h (nonexistent) +++ tags/1.2.3/src/obj_common.h (revision 8969) @@ -0,0 +1,136 @@ +/* + * 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 + * + */ + +#ifndef PCB_OBJ_COMMON_H +#define PCB_OBJ_COMMON_H + +#include +#include +#include +#include "flag.h" +#include "attrib.h" +#include "global_typedefs.h" + +/* 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 */ +}; + +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_attribute_list_t Attributes + + /* struct pcb_lib_entry_t *net */ + +/* 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. */ +typedef struct { + PCB_ANYOBJECTFIELDS; +} pcb_any_obj_t; + +/* Lines, rats, pads, etc. */ +typedef struct { + PCB_ANYLINEFIELDS; +} pcb_any_line_t; + +/*** Functions and macros used for hashing ***/ + +/* compare two strings and return 0 if they are equal. NULL == NULL means equal. */ +static inline PCB_FUNC_UNUSED 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; +} + +static inline PCB_FUNC_UNUSED unsigned pcb_hash_coord(pcb_coord_t c) +{ + return murmurhash(&(c), sizeof(pcb_coord_t)); +} + + +/* 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)) + +#endif Index: tags/1.2.3/src/obj_elem.c =================================================================== --- tags/1.2.3/src/obj_elem.c (nonexistent) +++ tags/1.2.3/src/obj_elem.c (revision 8969) @@ -0,0 +1,2023 @@ +/* + * 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 + * + */ + +/* 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" + +/* 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; + + new_obj = calloc(sizeof(pcb_element_t), 1); + 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); + 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_element_t *element; + + 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); + if (elementlist_length(&Buffer->Data->Element)) { + element = elementlist_first(&Buffer->Data->Element); + Buffer->X = element->MarkX; + Buffer->Y = element->MarkY; + } + else { + Buffer->X = 0; + Buffer->Y = 0; + } + 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; + + if (elementlist_length(&Buffer->Data->Element) != 1) { + pcb_message(PCB_MSG_ERROR, _("Error! Buffer doesn't contain a single element\n")); + 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_flag_t f = pcb_no_flags(); + pcb_flag_add(f, PCB_FLAG_VIA); + if (PCB_FLAG_TEST(PCB_FLAG_HOLE, pin)) + pcb_flag_add(f, PCB_FLAG_HOLE); + + pcb_via_new(Buffer->Data, pin->X, pin->Y, pin->Thickness, pin->Clearance, pin->Mask, pin->DrillingHole, pin->Number, f); + } + 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 ? gbottom : gtop); + 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); + } + 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_polygon_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); + + if (Buffer->Data->pcb == 0) + Buffer->Data->pcb = PCB; + + 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 + */ +#if 0 + 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; +#endif + 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); + EraseElement(Element); + pcb_undo_add_obj_to_mirror(PCB_TYPE_ELEMENT, Element, Element, Element, yoff); + pcb_element_mirror(PCB->Data, Element, yoff); + DrawElement(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; + +#ifdef DEBUG + printf("In ChangeElementText, updating old TextString %s to %s\n", old, new_name); +#endif + + if (pcb && which == PCB_ELEMNAME_IDX_VISIBLE()) + EraseElementName(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()) + DrawElementName(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()) + EraseElementName(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()) + DrawElementName(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()) + EraseElementName(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()) + DrawElementName(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, 0); + + 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; + + return RemoveElement_op(&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 *AddElementToBuffer(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 *MoveElementToBuffer(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; + + return element; +} + + +/* changes the drilling hole of all pins of an element; returns pcb_true if changed */ +void *ChangeElement2ndSize(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.absolute) ? ctx->chgsize.absolute : pin->DrillingHole + ctx->chgsize.delta; + 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); + ErasePin(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); + DrawPin(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 *ChangeElement1stSize(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.absolute) ? ctx->chgsize.absolute : pin->DrillingHole + ctx->chgsize.delta; + 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); + ErasePin(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); + DrawPin(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 *ChangeElementClearSize(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.absolute) ? ctx->chgsize.absolute : pin->Clearance + ctx->chgsize.delta; + 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); + ErasePin(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); + DrawPin(pin); + } + } + PCB_END_LOOP; + + PCB_PAD_LOOP(Element); + { + value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : pad->Clearance + ctx->chgsize.delta; + 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); + ErasePad(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); + DrawPad(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 *ChangeElementSize(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)) + EraseElement(Element); + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : line->Thickness + ctx->chgsize.delta; + 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.absolute) ? ctx->chgsize.absolute : arc->Thickness + ctx->chgsize.delta; + 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)) { + DrawElement(Element); + } + if (changed) + return (Element); + return (NULL); +} + +/* changes the scaling factor of a elementname object; returns pcb_true if changed */ +void *ChangeElementNameSize(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + int value = ctx->chgsize.absolute ? PCB_COORD_TO_MIL(ctx->chgsize.absolute) + : PCB_ELEM_TEXT_DESCRIPTION(Element).Scale + PCB_COORD_TO_MIL(ctx->chgsize.delta); + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, &Element->Name[0])) + return (NULL); + if (value <= PCB_MAX_TEXTSCALE && value >= PCB_MIN_TEXTSCALE) { + EraseElementName(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; + DrawElementName(Element); + return (Element); + } + return (NULL); +} + + +void *ChangeElementName(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 *ChangeElementNonetlist(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 *ChangeElementSquare(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 = ChangePinSquare(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = ChangePadSquare(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* sets the square flag of all pins on an element */ +void *SetElementSquare(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 = SetPinSquare(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = SetPadSquare(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* clears the square flag of all pins on an element */ +void *ClrElementSquare(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 = ClrPinSquare(ctx, Element, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ans = ClrPadSquare(ctx, Element, pad); + } + PCB_END_LOOP; + return (ans); +} + +/* changes the octagon flags of all pins of an element */ +void *ChangeElementOctagon(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); + { + ChangePinOctagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* sets the octagon flags of all pins of an element */ +void *SetElementOctagon(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); + { + SetPinOctagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* clears the octagon flags of all pins of an element */ +void *ClrElementOctagon(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); + { + ClrPinOctagon(ctx, Element, pin); + result = Element; + } + PCB_END_LOOP; + return (result); +} + +/* copies an element onto the PCB. Then does a draw. */ +void *CopyElement(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + +#ifdef DEBUG + printf("Entered CopyElement, 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)) { + DrawElementName(element); + DrawElementPackage(element); + } + if (PCB->PinOn) { + DrawElementPinsAndPads(element); + } +#ifdef DEBUG + printf(" ... Leaving CopyElement.\n"); +#endif + return (element); +} + +/* moves all names of an element to a new position */ +void *MoveElementName(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + if (pcb_silk_on(PCB) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + EraseElementName(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; + DrawElementName(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 *MoveElement(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + pcb_bool didDraw = pcb_false; + + if (pcb_silk_on(PCB) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + EraseElement(Element); + pcb_element_move(PCB->Data, Element, ctx->move.dx, ctx->move.dy); + DrawElementName(Element); + DrawElementPackage(Element); + didDraw = pcb_true; + } + else { + if (PCB->PinOn) + EraseElementPinsAndPads(Element); + pcb_element_move(PCB->Data, Element, ctx->move.dx, ctx->move.dy); + } + if (PCB->PinOn) { + DrawElementPinsAndPads(Element); + didDraw = pcb_true; + } + if (didDraw) + pcb_draw(); + return (Element); +} + +/* destroys a element */ +void *DestroyElement(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 *RemoveElement_op(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + /* erase from screen */ + if ((pcb_silk_on(PCB) || PCB->PinOn) && (PCB_FRONT(Element) || PCB->InvisibleObjectsOn)) { + EraseElement(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 *Rotate90Element(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + EraseElement(Element); + pcb_element_rotate90(PCB->Data, Element, ctx->rotate.center_x, ctx->rotate.center_y, ctx->rotate.number); + DrawElement(Element); + pcb_draw(); + return (Element); +} + +/* ---------------------------------------------------------------------- + * rotates the name of an element + */ +void *Rotate90ElementName(pcb_opctx_t *ctx, pcb_element_t *Element) +{ + EraseElementName(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; + DrawElementName(Element); + pcb_draw(); + return (Element); +} + +/*** draw ***/ +void draw_element_name(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(Output.fgGC, conf_core.appearance.color.element); + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element))) + pcb_gui->set_color(Output.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(Output.fgGC, conf_core.appearance.color.element_nonetlist); + else + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.element); + } + else + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.invisible_objects); + + DrawTextLowLevel(&PCB_ELEM_TEXT_VISIBLE(PCB, element), PCB->minSlk); + +} + +pcb_r_dir_t draw_element_name_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)) + draw_element_name(element); + return PCB_R_DIR_NOT_FOUND; +} + +void draw_element_pins_and_pads(pcb_element_t * element) +{ + PCB_PAD_LOOP(element); + { + if (pcb_draw_doing_pinout || pcb_draw_doing_assy || PCB_FRONT(pad) || PCB->InvisibleObjectsOn) + draw_pad(pad); + } + PCB_END_LOOP; + PCB_PIN_LOOP(element); + { + draw_pin(pin, pcb_true); + } + PCB_END_LOOP; +} + + +void draw_element_package(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(Output.fgGC, conf_core.appearance.color.element); + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.element_selected); + else if (PCB_FRONT(element)) + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.element); + else + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.invisible_objects); + + /* draw lines, arcs, text and pins */ + PCB_ELEMENT_PCB_LINE_LOOP(element); + { + _draw_line(line); + } + PCB_END_LOOP; + PCB_ARC_LOOP(element); + { + _draw_arc(arc); + } + PCB_END_LOOP; +} + +void draw_element(pcb_element_t *element) +{ + draw_element_package(element); + draw_element_name(element); + draw_element_pins_and_pads(element); +} + +pcb_r_dir_t draw_element_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)) + draw_element_package(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(Output.fgGC, invisible ? conf_core.appearance.color.invisible_mark : conf_core.appearance.color.element); + pcb_gui->set_line_cap(Output.fgGC, Trace_Cap); + pcb_gui->set_line_width(Output.fgGC, 0); + pcb_gui->draw_line(Output.fgGC, X - mark_size, Y, X, Y - mark_size); + pcb_gui->draw_line(Output.fgGC, X + mark_size, Y, X, Y - mark_size); + pcb_gui->draw_line(Output.fgGC, X - mark_size, Y, X, Y + mark_size); + pcb_gui->draw_line(Output.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(Output.fgGC, X, Y, X + 2 * mark_size, Y); + pcb_gui->draw_line(Output.fgGC, X, Y, X, Y - 4 * mark_size); + } +} + +pcb_r_dir_t draw_element_mark_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 EraseElement(pcb_element_t *Element) +{ + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + EraseLine(line); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + EraseArc(arc); + } + PCB_END_LOOP; + EraseElementName(Element); + EraseElementPinsAndPads(Element); + pcb_flag_erase(&Element->Flags); +} + +void EraseElementPinsAndPads(pcb_element_t *Element) +{ + PCB_PIN_LOOP(Element); + { + ErasePin(pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(Element); + { + ErasePad(pad); + } + PCB_END_LOOP; +} + +void EraseElementName(pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_HIDENAME, Element)) { + return; + } + DrawText(NULL, &PCB_ELEM_TEXT_VISIBLE(PCB, Element)); +} + +void DrawElement(pcb_element_t *Element) +{ + DrawElementPackage(Element); + DrawElementName(Element); + DrawElementPinsAndPads(Element); +} + +void DrawElementName(pcb_element_t *Element) +{ + if (PCB_FLAG_TEST(PCB_FLAG_HIDENAME, Element)) + return; + DrawText(NULL, &PCB_ELEM_TEXT_VISIBLE(PCB, Element)); +} + +void DrawElementPackage(pcb_element_t *Element) +{ + PCB_ELEMENT_PCB_LINE_LOOP(Element); + { + DrawLine(NULL, line); + } + PCB_END_LOOP; + PCB_ARC_LOOP(Element); + { + DrawArc(NULL, arc); + } + PCB_END_LOOP; +} + +void DrawElementPinsAndPads(pcb_element_t *Element) +{ + PCB_PAD_LOOP(Element); + { + if (pcb_draw_doing_pinout || pcb_draw_doing_assy || PCB_FRONT(pad) || PCB->InvisibleObjectsOn) + DrawPad(pad); + } + PCB_END_LOOP; + PCB_PIN_LOOP(Element); + { + DrawPin(pin); + } + PCB_END_LOOP; +} + Index: tags/1.2.3/src/obj_elem.h =================================================================== --- tags/1.2.3/src/obj_elem.h (nonexistent) +++ tags/1.2.3/src/obj_elem.h (revision 8969) @@ -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., 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 + * + */ + +/* 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.3/src/obj_elem_draw.h =================================================================== --- tags/1.2.3/src/obj_elem_draw.h (nonexistent) +++ tags/1.2.3/src/obj_elem_draw.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard draw of elements ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_element_name_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t draw_element_mark_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t draw_element_callback(const pcb_box_t * b, void *cl); +#endif + +void draw_element_package(pcb_element_t * element); +void draw_element_name(pcb_element_t * element); +void draw_element_pins_and_pads(pcb_element_t * element); +void draw_element(pcb_element_t *element); + +void EraseElement(pcb_element_t *Element); +void EraseElementPinsAndPads(pcb_element_t *Element); +void EraseElementName(pcb_element_t *Element); + +void DrawElement(pcb_element_t *Element); +void DrawElementName(pcb_element_t *Element); +void DrawElementPackage(pcb_element_t *Element); +void DrawElementPinsAndPads(pcb_element_t *Element); Index: tags/1.2.3/src/obj_elem_list.c =================================================================== --- tags/1.2.3/src/obj_elem_list.c (nonexistent) +++ tags/1.2.3/src/obj_elem_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_elem_list.h =================================================================== --- tags/1.2.3/src/obj_elem_list.h (nonexistent) +++ tags/1.2.3/src/obj_elem_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_elem_op.h =================================================================== --- tags/1.2.3/src/obj_elem_op.h (nonexistent) +++ tags/1.2.3/src/obj_elem_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on elements ***/ + +#include "operation.h" + +void *AddElementToBuffer(pcb_opctx_t *ctx, pcb_element_t *Element); +void *MoveElementToBuffer(pcb_opctx_t *ctx, pcb_element_t * element); +void *ClrElementOctagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *SetElementOctagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementOctagon(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ClrElementSquare(pcb_opctx_t *ctx, pcb_element_t *Element); +void *SetElementSquare(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementSquare(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementNonetlist(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementName(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementNameSize(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementSize(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElementClearSize(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElement1stSize(pcb_opctx_t *ctx, pcb_element_t *Element); +void *ChangeElement2ndSize(pcb_opctx_t *ctx, pcb_element_t *Element); +void *CopyElement(pcb_opctx_t *ctx, pcb_element_t *Element); +void *MoveElementName(pcb_opctx_t *ctx, pcb_element_t *Element); +void *MoveElement(pcb_opctx_t *ctx, pcb_element_t *Element); +void *DestroyElement(pcb_opctx_t *ctx, pcb_element_t *Element); +void *RemoveElement_op(pcb_opctx_t *ctx, pcb_element_t *Element); +void *Rotate90Element(pcb_opctx_t *ctx, pcb_element_t *Element); +void *Rotate90ElementName(pcb_opctx_t *ctx, pcb_element_t *Element); + Index: tags/1.2.3/src/obj_line.c =================================================================== --- tags/1.2.3/src/obj_line.c (nonexistent) +++ tags/1.2.3/src/obj_line.c (revision 8969) @@ -0,0 +1,888 @@ +/* + * 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 + * + */ + +/* 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" + +/* TODO: maybe remove this and move lines from draw here? */ +#include "draw.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); + 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; + 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 differ */ + && PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, line) == PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, i)) { + 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.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); +} + +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 */ +} + + +/*** ops ***/ + +/* copies a line to buffer */ +void *AddLineToBuffer(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)); + if (line && Line->Number) + line->Number = pcb_strdup(Line->Number); + return (line); +} + +/* moves a line to buffer */ +void *MoveLineToBuffer(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); + return (line); +} + +/* changes the size of a line */ +void *ChangeLineSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Line->Thickness + ctx->chgsize.delta; + + 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); + EraseLine(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->Thickness = value; + 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); + DrawLine(Layer, Line); + return (Line); + } + return (NULL); +} + +/*changes the clearance size of a line */ +void *ChangeLineClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Line->Clearance + ctx->chgsize.delta; + + 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, MAX(value, 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(PCB->Data, PCB_TYPE_LINE, Layer, Line); + EraseLine(Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + Line->Clearance = value; + if (Line->Clearance == 0) { + PCB_FLAG_CLEAR(PCB_FLAG_CLEARLINE, Line); + Line->Clearance = PCB_MIL_TO_COORD(10); + } + 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); + DrawLine(Layer, Line); + return (Line); + } + return (NULL); +} + +/* changes the name of a line */ +void *ChangeLineName(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 *ChangeLineJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Line)) + return (NULL); + EraseLine(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(PCB->Data, PCB_TYPE_LINE, Layer, Line); + } + pcb_undo_add_obj_to_flag(PCB_TYPE_LINE, Layer, Line, 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(PCB->Data, PCB_TYPE_LINE, Layer, Line); + } + DrawLine(Layer, Line); + return (Line); +} + +/* sets the clearance flag of a line */ +void *SetLineJoin(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 ChangeLineJoin(ctx, Layer, Line); +} + +/* clears the clearance flag of a line */ +void *ClrLineJoin(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 ChangeLineJoin(ctx, Layer, Line); +} + +/* copies a line */ +void *CopyLine(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); + if (Line->Number) + line->Number = pcb_strdup(Line->Number); + DrawLine(Layer, line); + pcb_undo_add_obj_to_create(PCB_TYPE_LINE, Layer, line, line); + return (line); +} + +/* moves a line */ +void *MoveLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + if (Layer->On) + EraseLine(Line); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + pcb_r_delete_entry(Layer->line_tree, (pcb_box_t *) Line); + pcb_line_move(Line, ctx->move.dx, ctx->move.dy); + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + if (Layer->On) { + DrawLine(Layer, Line); + pcb_draw(); + } + return (Line); +} + +/* moves one end of a line */ +void *MoveLinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + if (Layer) { + if (Layer->On) + EraseLine(Line); + pcb_poly_restore_to_poly(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(PCB->Data, PCB_TYPE_LINE, Layer, Line); + if (Layer->On) { + DrawLine(Layer, Line); + pcb_draw(); + } + return (Line); + } + else { /* must be a rat */ + + if (PCB->RatOn) + EraseRat((pcb_rat_t *) Line); + pcb_r_delete_entry(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(PCB->Data->rat_tree, &Line->BoundingBox, 0); + if (PCB->RatOn) { + DrawRat((pcb_rat_t *) Line); + pcb_draw(); + } + return (Line); + } +} + +/* moves one end of a line */ +void *MoveLinePointWithRoute(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 MoveLinePoint(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(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 *MoveLineToLayerLowLevel(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); + 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); + DrawVia(via); + } + longjmp(i->env, 1); +} + +void *MoveLineToLayer(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->On) { + DrawLine(Layer, Line); + pcb_draw(); + } + if (((long int) ctx->move.dst_layer == -1) || ctx->move.dst_layer == Layer) + return (Line); + + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_LINE, Layer, Line, Line); + if (Layer->On) + EraseLine(Line); + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + newone = (pcb_line_t *) MoveLineToLayerLowLevel(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->On) + DrawLine(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(PCB, pcb_layer_id(PCB->Data, 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 *DestroyLine(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 *RemoveLinePoint(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 RemoveLine_op(ctx, Layer, Line); + } + pcb_move_obj(PCB_TYPE_LINE_POINT, Layer, info.line, info.point, other.X - Point->X, other.Y - Point->Y); + return (RemoveLine_op(ctx, Layer, Line)); +} + +/* removes a line from a layer */ +void *RemoveLine_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line) +{ + /* erase from screen */ + if (Layer->On) { + EraseLine(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 RemoveLine_op(&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) +{ + 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); +} + +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) +{ + EraseLine(Line); + if (Layer) { + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + 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) { + pcb_r_insert_entry(Layer->line_tree, (pcb_box_t *) Line, 0); + pcb_poly_clear_from_poly(PCB->Data, PCB_TYPE_LINE, Layer, Line); + DrawLine(Layer, Line); + } + else { + pcb_r_insert_entry(PCB->Data->rat_tree, (pcb_box_t *) Line, 0); + DrawRat((pcb_rat_t *) Line); + } + pcb_draw(); +} + +/* rotates a line's point */ +void *Rotate90LinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point) +{ + pcb_point_t *center; + + rotate_line1(Layer, Line); + + if ((Point->X == Line->Point1.X) && (Point->Y == Line->Point1.Y)) + center = &Line->Point2; + else + center = &Line->Point1; + + pcb_point_rotate90(Point, center->X, center->Y, ctx->rotate.number); + + rotate_line2(Layer, Line); + return Line; +} + +/* rotates a line */ +void *Rotate90Line(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; +} + +/* inserts a point into a line */ +void *InsertPointIntoLine(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); + EraseLine(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); + DrawLine(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_undo_add_obj_to_create(PCB_TYPE_LINE, Layer, line, line); + DrawLine(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); +} + +/*** draw ***/ +void _draw_line(pcb_line_t * line) +{ + PCB_DRAW_BBOX(line); + pcb_gui->set_line_cap(Output.fgGC, Trace_Cap); + if (conf_core.editor.thin_draw) + pcb_gui->set_line_width(Output.fgGC, 0); + else + pcb_gui->set_line_width(Output.fgGC, line->Thickness); + + pcb_gui->draw_line(Output.fgGC, line->Point1.X, line->Point1.Y, line->Point2.X, line->Point2.Y); +} + +void draw_line(pcb_layer_t * layer, pcb_line_t * line) +{ + 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->SelectedColor; + else + color = conf_core.appearance.color.connected; + } + else + color = layer->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(Output.fgGC, color); + _draw_line(line); +} + +pcb_r_dir_t draw_line_callback(const pcb_box_t * b, void *cl) +{ + draw_line((pcb_layer_t *) cl, (pcb_line_t *) b); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a line on a layer */ +void EraseLine(pcb_line_t *Line) +{ + pcb_draw_invalidate(Line); + pcb_flag_erase(&Line->Flags); +} + +void DrawLine(pcb_layer_t *Layer, pcb_line_t *Line) +{ + pcb_draw_invalidate(Line); +} + Index: tags/1.2.3/src/obj_line.h =================================================================== --- tags/1.2.3/src/obj_line.h (nonexistent) +++ tags/1.2.3/src/obj_line.h (revision 8969) @@ -0,0 +1,129 @@ +/* + * 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 + * + */ + +/* 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); +void *pcb_line_destroy(pcb_layer_t *Layer, pcb_line_t *Line); + + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_line_on_layer(pcb_layer_t *Layer, pcb_line_t *Line); + +void pcb_line_bbox(pcb_line_t *Line); +void pcb_line_rotate90(pcb_line_t *Line, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_line_rotate(pcb_layer_t *layer, pcb_line_t *line, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +void pcb_line_mirror(pcb_layer_t *layer, pcb_line_t *line); +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); + + +/* 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->On) \ + PCB_LINE_LOOP(layer) + +#endif Index: tags/1.2.3/src/obj_line_draw.h =================================================================== --- tags/1.2.3/src/obj_line_draw.h (nonexistent) +++ tags/1.2.3/src/obj_line_draw.h (revision 8969) @@ -0,0 +1,37 @@ +/* + * 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 + * + */ + +/*** Standard draw of lines ***/ + +/* Include rtree.h for this */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_line_callback(const pcb_box_t * b, void *cl); +#endif + +void _draw_line(pcb_line_t * line); +void draw_line(pcb_layer_t * layer, pcb_line_t * line); +void EraseLine(pcb_line_t *Line); +void DrawLine(pcb_layer_t *Layer, pcb_line_t *Line); Index: tags/1.2.3/src/obj_line_drcenf.c =================================================================== --- tags/1.2.3/src/obj_line_drcenf.c (nonexistent) +++ tags/1.2.3/src/obj_line_drcenf.c (revision 8969) @@ -0,0 +1,547 @@ +/* + * 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., 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 + * + */ + +#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(PCB,pcb_layer_id(PCB->Data, CURRENT)) & PCB_LYT_COPPER)) + flags |= PCB_FLAG_FOUND; + + /* I need at least one point */ + if (line->State == PCB_CH_STATE_FIRST) + return; + + /* don't draw outline when ctrl key is pressed */ + if (conf_core.editor.mode == PCB_MODE_LINE && pcb_gui->control_is_pressed()) { + line->draw = pcb_false; + return; + } + else + line->draw = pcb_true; + + 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_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_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.3/src/obj_line_list.c =================================================================== --- tags/1.2.3/src/obj_line_list.c (nonexistent) +++ tags/1.2.3/src/obj_line_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_line_list.h" +#include Index: tags/1.2.3/src/obj_line_list.h =================================================================== --- tags/1.2.3/src/obj_line_list.h (nonexistent) +++ tags/1.2.3/src/obj_line_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_line_op.h =================================================================== --- tags/1.2.3/src/obj_line_op.h (nonexistent) +++ tags/1.2.3/src/obj_line_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on line segments ***/ + +#include "operation.h" + +void *AddLineToBuffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *ChangeLineSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *ChangeLineClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *ChangeLineName(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *ChangeLineJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *SetLineJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *ClrLineJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *InsertPointIntoLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *MoveLineToBuffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_line_t * line); +void *CopyLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *MoveLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *MoveLinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *MoveLinePointWithRoute(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *MoveLineToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_line_t * line, pcb_layer_t * Destination); +void *MoveLineToLayer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_line_t * Line); +void *DestroyLine(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *RemoveLinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *RemoveLine_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); +void *Rotate90LinePoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line, pcb_point_t *Point); +void *Rotate90Line(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_line_t *Line); + + + Index: tags/1.2.3/src/obj_pad.c =================================================================== --- tags/1.2.3/src/obj_pad.c (nonexistent) +++ tags/1.2.3/src/obj_pad.c (revision 8969) @@ -0,0 +1,532 @@ +/* + * 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 + * + */ + +/* 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" + +/*** 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); + 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); +} + +/* 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); + ErasePad(Pad); + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, Pad, Pad, Pad); + PCB_FLAG_TOGGLE(PCB_FLAG_NOPASTE, Pad); + DrawPad(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; +} + +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); +} + + +/*** ops ***/ + +/* changes the size of a pad */ +void *ChangePadSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pad->Thickness + ctx->chgsize.delta; + + 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); + ErasePad(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); + DrawPad(Pad); + return (Pad); + } + return (NULL); +} + +/* changes the clearance size of a pad */ +void *ChangePadClearSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pad->Clearance + ctx->chgsize.delta; + + 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.delta < 0 && value < PCB->Bloat * 2) + value = 0; + if ((ctx->chgsize.delta > 0 || ctx->chgsize.absolute) && 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); + ErasePad(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); + DrawPad(Pad); + return Pad; +} + +/* changes the name of a pad */ +void *ChangePadName(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_DISPLAYNAME, Pad)) { + ErasePadName(Pad); + Pad->Name = ctx->chgname.new_name; + DrawPadName(Pad); + } + else + Pad->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the number of a pad */ +void *ChangePadNum(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_DISPLAYNAME, Pad)) { + ErasePadName(Pad); + Pad->Number = ctx->chgname.new_name; + DrawPadName(Pad); + } + else + Pad->Number = ctx->chgname.new_name; + return (old); +} + +/* changes the square flag of a pad */ +void *ChangePadSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pad)) + return (NULL); + ErasePad(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(PCB_TYPE_PAD, Element, Pad, 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); + DrawPad(Pad); + return (Pad); +} + +/* sets the square flag of a pad */ +void *SetPadSquare(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 (ChangePadSquare(ctx, Element, Pad)); +} + + +/* clears the square flag of a pad */ +void *ClrPadSquare(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 (ChangePadSquare(ctx, Element, Pad)); +} + +/* changes the mask size of a pad */ +void *ChangePadMaskSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pad->Mask + ctx->chgsize.delta; + + value = MAX(value, 0); + if (value == Pad->Mask && ctx->chgsize.absolute == 0) + value = Pad->Thickness; + if (value != Pad->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PAD, Element, Pad, Pad); + ErasePad(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)); + DrawPad(Pad); + return (Pad); + } + return (NULL); +} + +/*** draw ***/ +static void draw_pad_name(pcb_pad_t * pad) +{ + pcb_box_t box; + pcb_bool vert; + 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 (PCB_FLAG_INTCONN_GET(pad) > 0) + pcb_snprintf(buff, sizeof(buff), "%s[%d]", pn, PCB_FLAG_INTCONN_GET(pad)); + else + strcpy(buff, pn); + text.TextString = buff; + + /* 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; + } + 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; + } + + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.pin_name); + + text.Flags = 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; + + DrawTextLowLevel(&text, 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)) + pcb_gui->thindraw_pcb_pad(gc, pad, clear, mask); + else + pcb_gui->fill_pcb_pad(gc, pad, clear, mask); +} + +void draw_pad(pcb_pad_t * pad) +{ + const char *color = NULL; + char buf[sizeof("#XXXXXX")]; + + if (pcb_draw_doing_pinout) + pcb_gui->set_color(Output.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_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(Output.fgGC, color); + + _draw_pad(Output.fgGC, pad, pcb_false, pcb_false); + + if (pcb_draw_doing_pinout || PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, pad)) + draw_pad_name(pad); +} + +pcb_r_dir_t draw_pad_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)) + draw_pad(pad); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t clear_pad_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(Output.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_draw_paste_auto(int side, const pcb_box_t * drawn_area) +{ + pcb_gui->set_color(Output.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(Output.fgGC, pad, pcb_true, pcb_true); + else + _draw_pad(Output.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 ErasePad(pcb_pad_t *Pad) +{ + pcb_draw_invalidate(Pad); + if (PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Pad)) + ErasePadName(Pad); + pcb_flag_erase(&Pad->Flags); +} + +void ErasePadName(pcb_pad_t *Pad) +{ + GatherPadName(Pad); +} + +void DrawPad(pcb_pad_t *Pad) +{ + pcb_draw_invalidate(Pad); + if (pcb_draw_doing_pinout || PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Pad)) + DrawPadName(Pad); +} + +void DrawPadName(pcb_pad_t *Pad) +{ + GatherPadName(Pad); +} Index: tags/1.2.3/src/obj_pad.h =================================================================== --- tags/1.2.3/src/obj_pad.h (nonexistent) +++ tags/1.2.3/src/obj_pad.h (revision 8969) @@ -0,0 +1,85 @@ +/* + * 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 + * + */ + +/* 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; + void *Spare; + 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); + +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); +unsigned int pcb_pad_hash(const pcb_element_t *e, 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.3/src/obj_pad_draw.h =================================================================== --- tags/1.2.3/src/obj_pad_draw.h (nonexistent) +++ tags/1.2.3/src/obj_pad_draw.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard draw on pads ***/ + + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_pad_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t clear_pad_callback(const pcb_box_t * b, void *cl); +#endif + +void draw_pad(pcb_pad_t * pad); +void pcb_draw_paste_auto(int side, const pcb_box_t * drawn_area); +void ErasePad(pcb_pad_t *Pad); +void ErasePadName(pcb_pad_t *Pad); +void DrawPad(pcb_pad_t *Pad); +void DrawPadName(pcb_pad_t *Pad); Index: tags/1.2.3/src/obj_pad_list.c =================================================================== --- tags/1.2.3/src/obj_pad_list.c (nonexistent) +++ tags/1.2.3/src/obj_pad_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_pad_list.h" +#include Index: tags/1.2.3/src/obj_pad_list.h =================================================================== --- tags/1.2.3/src/obj_pad_list.h (nonexistent) +++ tags/1.2.3/src/obj_pad_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_pad_op.h =================================================================== --- tags/1.2.3/src/obj_pad_op.h (nonexistent) +++ tags/1.2.3/src/obj_pad_op.h (revision 8969) @@ -0,0 +1,42 @@ +/* + * 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 + * + */ + +/*** Standard operations on pads ***/ + +#include "operation.h" + +void *ChangePadSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ChangePadClearSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ChangePadName(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ChangePadNum(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ChangePadSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *SetPadSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ClrPadSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); +void *ChangePadMaskSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pad_t *Pad); + + + + Index: tags/1.2.3/src/obj_pinvia.c =================================================================== --- tags/1.2.3/src/obj_pinvia.c (nonexistent) +++ tags/1.2.3/src/obj_pinvia.c (revision 8969) @@ -0,0 +1,1061 @@ +/* + * 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 + * + */ + +/* 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" + +/* 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); + 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); + 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); +} + +/* 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); +} + +/* 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_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) +{ + via->X = PCB_SWAP_X(via->X); + via->Y = PCB_SWAP_Y(via->Y); +} + +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; +} + +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); +} + + +/*** ops ***/ +/* copies a via to paste buffer */ +void *AddViaToBuffer(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + return (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))); +} + +/* moves a via to paste buffer without allocating memory for the name */ +void *MoveViaToBuffer(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); + return via; +} + +/* changes the thermal on a via */ +void *ChangeViaThermal(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(PCB_TYPE_VIA, Via, Via, 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); + DrawVia(Via); + return Via; +} + +/* changes the thermal on a pin */ +void *ChangePinThermal(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(PCB_TYPE_PIN, element, Pin, 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); + DrawPin(Pin); + return Pin; +} + +/* changes the size of a via */ +void *ChangeViaSize(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = ctx->chgsize.absolute ? ctx->chgsize.absolute : Via->Thickness + ctx->chgsize.delta; + + 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); + EraseVia(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); + DrawVia(Via); + return (Via); + } + return (NULL); +} + +/* changes the drilling hole of a via */ +void *ChangeVia2ndSize(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Via->DrillingHole + ctx->chgsize.delta; + + 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); + EraseVia(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); + DrawVia(Via); + return (Via); + } + return (NULL); +} + +/* changes the drilling hole of a pin */ +void *ChangePin2ndSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pin->DrillingHole + ctx->chgsize.delta; + + 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); + ErasePin(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); + DrawPin(Pin); + return (Pin); + } + return (NULL); +} + + +/* changes the clearance size of a via */ +void *ChangeViaClearSize(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Via->Clearance + ctx->chgsize.delta; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (ctx->chgsize.delta < 0 && value < PCB->Bloat * 2) + value = 0; + if ((ctx->chgsize.delta > 0 || ctx->chgsize.absolute) && 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); + EraseVia(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); + DrawVia(Via); + Via->Element = NULL; + return (Via); +} + + +/* changes the size of a pin */ +void *ChangePinSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pin->Thickness + ctx->chgsize.delta; + + 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); + ErasePin(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); + DrawPin(Pin); + return (Pin); + } + return (NULL); +} + +/* changes the clearance size of a pin */ +void *ChangePinClearSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pin->Clearance + ctx->chgsize.delta; + + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + if (value < 0) + value = 0; + value = MIN(PCB_MAX_LINESIZE, value); + if (ctx->chgsize.delta < 0 && value < PCB->Bloat * 2) + value = 0; + if ((ctx->chgsize.delta > 0 || ctx->chgsize.absolute) && 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); + ErasePin(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); + DrawPin(Pin); + return (Pin); +} + +/* changes the name of a via */ +void *ChangeViaName(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + char *old = Via->Name; + + if (PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Via)) { + ErasePinName(Via); + Via->Name = ctx->chgname.new_name; + DrawPinName(Via); + } + else + Via->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the name of a pin */ +void *ChangePinName(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_DISPLAYNAME, Pin)) { + ErasePinName(Pin); + Pin->Name = ctx->chgname.new_name; + DrawPinName(Pin); + } + else + Pin->Name = ctx->chgname.new_name; + return (old); +} + +/* changes the number of a pin */ +void *ChangePinNum(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_DISPLAYNAME, Pin)) { + ErasePinName(Pin); + Pin->Number = ctx->chgname.new_name; + DrawPinName(Pin); + } + else + Pin->Number = ctx->chgname.new_name; + return (old); +} + + +/* changes the square flag of a via */ +void *ChangeViaSquare(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + EraseVia(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(PCB_TYPE_VIA, NULL, Via, Via); + PCB_FLAG_SQUARE_ASSIGN(ctx->chgsize.absolute, Via); + if (ctx->chgsize.absolute == 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); + DrawVia(Via); + return (Via); +} + +/* changes the square flag of a pin */ +void *ChangePinSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + ErasePin(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(PCB_TYPE_PIN, Element, Pin, Pin); + PCB_FLAG_SQUARE_ASSIGN(ctx->chgsize.absolute, Pin); + if (ctx->chgsize.absolute == 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); + DrawPin(Pin); + return (Pin); +} + +/* sets the square flag of a pin */ +void *SetPinSquare(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 (ChangePinSquare(ctx, Element, Pin)); +} + +/* clears the square flag of a pin */ +void *ClrPinSquare(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 (ChangePinSquare(ctx, Element, Pin)); +} + +/* changes the octagon flag of a via */ +void *ChangeViaOctagon(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Via)) + return (NULL); + EraseVia(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(PCB_TYPE_VIA, Via, Via, 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); + DrawVia(Via); + return (Via); +} + +/* sets the octagon flag of a via */ +void *SetViaOctagon(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 (ChangeViaOctagon(ctx, Via)); +} + +/* clears the octagon flag of a via */ +void *ClrViaOctagon(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 (ChangeViaOctagon(ctx, Via)); +} + +/* changes the octagon flag of a pin */ +void *ChangePinOctagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Pin)) + return (NULL); + ErasePin(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(PCB_TYPE_PIN, Element, Pin, 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); + DrawPin(Pin); + return (Pin); +} + +/* sets the octagon flag of a pin */ +void *SetPinOctagon(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 (ChangePinOctagon(ctx, Element, Pin)); +} + +/* clears the octagon flag of a pin */ +void *ClrPinOctagon(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 (ChangePinOctagon(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); + EraseVia(Via); + pcb_undo_add_obj_to_flag(PCB_TYPE_VIA, Via, Via, 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); + DrawVia(Via); + pcb_draw(); + return (pcb_true); +} + +/* changes the mask size of a pin */ +void *ChangePinMaskSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin) +{ + pcb_coord_t value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Pin->Mask + ctx->chgsize.delta; + + value = MAX(value, 0); + if (value == Pin->Mask && ctx->chgsize.absolute == 0) + value = Pin->Thickness; + if (value != Pin->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_PIN, Element, Pin, Pin); + ErasePin(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)); + DrawPin(Pin); + return (Pin); + } + return (NULL); +} + +/* changes the mask size of a via */ +void *ChangeViaMaskSize(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + pcb_coord_t value; + + value = (ctx->chgsize.absolute) ? ctx->chgsize.absolute : Via->Mask + ctx->chgsize.delta; + value = MAX(value, 0); + if (value != Via->Mask) { + pcb_undo_add_obj_to_mask_size(PCB_TYPE_VIA, Via, Via, Via); + EraseVia(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); + DrawVia(Via); + return (Via); + } + return (NULL); +} + +/* copies a via */ +void *CopyVia(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); + DrawVia(via); + pcb_undo_add_obj_to_create(PCB_TYPE_VIA, via, via, via); + return (via); +} + +/* moves a via */ +void *MoveVia(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_via_move(Via, ctx->move.dx, ctx->move.dy); + if (PCB->ViaOn) + EraseVia(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); + if (PCB->ViaOn) { + DrawVia(Via); + pcb_draw(); + } + return (Via); +} + +/* destroys a via */ +void *DestroyVia(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 *RemoveVia(pcb_opctx_t *ctx, pcb_pin_t *Via) +{ + /* erase from screen and memory */ + if (PCB->ViaOn) { + EraseVia(Via); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_VIA, Via, Via, Via); + return NULL; +} + +/*** 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) { + 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 + color = conf_core.appearance.color.via; + } + else { + 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 + color = conf_core.appearance.color.pin; + } + + pcb_gui->set_color(Output.fgGC, color); +} + +static void _draw_pv_name(pcb_pin_t * pv) +{ + pcb_box_t box; + pcb_bool vert; + pcb_text_t text; + char buff[128]; + const char *pn; + + PCB_DRAW_BBOX(pv); + + if (!pv->Name || !pv->Name[0]) { + pn = PCB_EMPTY(pv->Number); + } + else { + pn = PCB_EMPTY(conf_core.editor.show_number ? pv->Number : pv->Name); + if (pn == NULL) + pn = "n/a"; + } + + if (PCB_FLAG_INTCONN_GET(pv) > 0) + pcb_snprintf(buff, sizeof(buff), "%s[%d]", pn, PCB_FLAG_INTCONN_GET(pv)); + else + strcpy(buff, pn); + text.TextString = buff; + + vert = PCB_FLAG_TEST(PCB_FLAG_EDGE2, pv); + + if (vert) { + box.X1 = pv->X - pv->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + box.Y1 = pv->Y - pv->DrillingHole / 2 - conf_core.appearance.pinout.text_offset_x; + } + else { + box.X1 = pv->X + pv->DrillingHole / 2 + conf_core.appearance.pinout.text_offset_x; + box.Y1 = pv->Y - pv->Thickness / 2 + conf_core.appearance.pinout.text_offset_y; + } + + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.pin_name); + + text.Flags = pcb_no_flags(); + /* Set font height to approx 56% of pin thickness */ + text.Scale = 56 * pv->Thickness / PCB_FONT_CAPHEIGHT; + text.X = box.X1; + text.Y = box.Y1; + text.fid = 0; + text.Direction = vert ? 1 : 0; + + if (pcb_gui->gui) + pcb_draw_doing_pinout++; + DrawTextLowLevel(&text, 0); + if (pcb_gui->gui) + pcb_draw_doing_pinout--; +} + +static void _draw_pv(pcb_pin_t *pv, pcb_bool draw_hole) +{ + if (conf_core.editor.thin_draw) + pcb_gui->thindraw_pcb_pv(Output.fgGC, Output.fgGC, pv, draw_hole, pcb_false); + else + pcb_gui->fill_pcb_pv(Output.fgGC, Output.bgGC, pv, draw_hole, pcb_false); + + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pv) && PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, pv)) + _draw_pv_name(pv); +} + +void draw_pin(pcb_pin_t *pin, pcb_bool draw_hole) +{ + SetPVColor(pin, PCB_TYPE_PIN); + _draw_pv(pin, draw_hole); +} + +pcb_r_dir_t draw_pin_callback(const pcb_box_t * b, void *cl) +{ + draw_pin((pcb_pin_t *) b, pcb_false); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t clear_pin_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) + pcb_gui->thindraw_pcb_pv(Output.pmGC, Output.pmGC, pin, pcb_false, pcb_true); + else + pcb_gui->fill_pcb_pv(Output.pmGC, Output.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 draw_via_callback(const pcb_box_t * b, void *cl) +{ + draw_via((pcb_pin_t *) b, pcb_false); + return PCB_R_DIR_FOUND_CONTINUE; +} + +pcb_r_dir_t draw_hole_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 (conf_core.editor.thin_draw) { + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, pv)) { + pcb_gui->set_line_cap(Output.fgGC, Round_Cap); + pcb_gui->set_line_width(Output.fgGC, 0); + pcb_gui->draw_arc(Output.fgGC, pv->X, pv->Y, pv->DrillingHole / 2, pv->DrillingHole / 2, 0, 360); + } + } + else + pcb_gui->fill_circle(Output.bgGC, 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(Output.fgGC, color); + + pcb_gui->set_line_cap(Output.fgGC, Round_Cap); + pcb_gui->set_line_width(Output.fgGC, 0); + pcb_gui->draw_arc(Output.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 EraseVia(pcb_pin_t *Via) +{ + pcb_draw_invalidate(Via); + if (PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Via)) + EraseViaName(Via); + pcb_flag_erase(&Via->Flags); +} + +void EraseViaName(pcb_pin_t *Via) +{ + GatherPVName(Via); +} + +void ErasePin(pcb_pin_t *Pin) +{ + pcb_draw_invalidate(Pin); + if (PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Pin)) + ErasePinName(Pin); + pcb_flag_erase(&Pin->Flags); +} + +void ErasePinName(pcb_pin_t *Pin) +{ + GatherPVName(Pin); +} + +void DrawVia(pcb_pin_t *Via) +{ + pcb_draw_invalidate(Via); + if (!PCB_FLAG_TEST(PCB_FLAG_HOLE, Via) && PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Via)) + DrawViaName(Via); +} + +void DrawViaName(pcb_pin_t *Via) +{ + GatherPVName(Via); +} + +void DrawPin(pcb_pin_t *Pin) +{ + pcb_draw_invalidate(Pin); + if ((!PCB_FLAG_TEST(PCB_FLAG_HOLE, Pin) && PCB_FLAG_TEST(PCB_FLAG_DISPLAYNAME, Pin)) + || pcb_draw_doing_pinout) + DrawPinName(Pin); +} + +void DrawPinName(pcb_pin_t *Pin) +{ + GatherPVName(Pin); +} Index: tags/1.2.3/src/obj_pinvia.h =================================================================== --- tags/1.2.3/src/obj_pinvia.h (nonexistent) +++ tags/1.2.3/src/obj_pinvia.h (revision 8969) @@ -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., 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 + * + */ + +/* 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; + void *Spare; + 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_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); + +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); +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); +unsigned int pcb_pin_hash(const pcb_element_t *e, 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.3/src/obj_pinvia_draw.h =================================================================== --- tags/1.2.3/src/obj_pinvia_draw.h (nonexistent) +++ tags/1.2.3/src/obj_pinvia_draw.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard draw on pins and vias ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_pin_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t clear_pin_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t draw_via_callback(const pcb_box_t * b, void *cl); +pcb_r_dir_t draw_hole_callback(const pcb_box_t * b, void *cl); +#endif + + +void draw_pin(pcb_pin_t *pin, pcb_bool draw_hole); +void EraseVia(pcb_pin_t *Via); +void EraseViaName(pcb_pin_t *Via); +void ErasePin(pcb_pin_t *Pin); +void ErasePinName(pcb_pin_t *Pin); +void DrawVia(pcb_pin_t *Via); +void DrawViaName(pcb_pin_t *Via); +void DrawPin(pcb_pin_t *Pin); +void DrawPinName(pcb_pin_t *Pin); Index: tags/1.2.3/src/obj_pinvia_list.c =================================================================== --- tags/1.2.3/src/obj_pinvia_list.c (nonexistent) +++ tags/1.2.3/src/obj_pinvia_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_pinvia_list.h" +#include Index: tags/1.2.3/src/obj_pinvia_list.h =================================================================== --- tags/1.2.3/src/obj_pinvia_list.h (nonexistent) +++ tags/1.2.3/src/obj_pinvia_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_pinvia_op.h =================================================================== --- tags/1.2.3/src/obj_pinvia_op.h (nonexistent) +++ tags/1.2.3/src/obj_pinvia_op.h (revision 8969) @@ -0,0 +1,60 @@ +/* + * 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 + * + */ + +/*** Standard operations on pins and vias ***/ + +#include "operation.h" + +void *AddViaToBuffer(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *MoveViaToBuffer(pcb_opctx_t *ctx, pcb_pin_t * via); +void *ChangeViaThermal(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePinThermal(pcb_opctx_t *ctx, pcb_element_t *element, pcb_pin_t *Pin); +void *ChangeViaSize(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangeVia2ndSize(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePin2ndSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangeViaClearSize(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePinSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangePinClearSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangeViaName(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePinName(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangePinNum(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangeViaSquare(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePinSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *SetPinSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ClrPinSquare(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangeViaOctagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *SetViaOctagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ClrViaOctagon(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *ChangePinOctagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *SetPinOctagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ClrPinOctagon(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +pcb_bool pcb_pin_change_hole(pcb_pin_t *Via); +void *ChangePinMaskSize(pcb_opctx_t *ctx, pcb_element_t *Element, pcb_pin_t *Pin); +void *ChangeViaMaskSize(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *CopyVia(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *MoveVia(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *DestroyVia(pcb_opctx_t *ctx, pcb_pin_t *Via); +void *RemoveVia(pcb_opctx_t *ctx, pcb_pin_t *Via); Index: tags/1.2.3/src/obj_pinvia_therm.c =================================================================== --- tags/1.2.3/src/obj_pinvia_therm.c (nonexistent) +++ tags/1.2.3/src/obj_pinvia_therm.c (revision 8969) @@ -0,0 +1,438 @@ +/* + * 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., 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 + * + */ + +/* negative thermal finger polygons */ + +#include "config.h" + +#include +#include + +#include "board.h" +#include "polygon.h" +#include "obj_pinvia_therm.h" + +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 *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; + + p = pcb_poly_from_octagon(pin->X, pin->Y, w, PCB_FLAG_SQUARE_GET(pin)); + p2 = pcb_poly_from_octagon(pin->X, pin->Y, pin->Thickness, PCB_FLAG_SQUARE_GET(pin)); + /* make full clearance ring */ + pcb_polyarea_boolean_free(p, p2, &m, PCB_PBO_SUB); + switch (style) { + default: + case 1: + p = diag_line(pin->X, pin->Y, w, t, pcb_true); + pcb_polyarea_boolean_free(m, p, &p2, PCB_PBO_SUB); + p = 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 *p, pcb_pin_t *pin, pcb_cardinal_t laynum) +{ + pcb_arc_t a; + pcb_polyarea_t *pa, *arc; + 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); + /* must be circular */ + switch (style) { + case 1: + case 2: + { + pcb_polyarea_t *m; + pcb_coord_t t = (pin->Thickness + pin->Clearance) / 2; + pcb_coord_t w = 0.5 * pcb->ThermScale * pin->Clearance; + pa = pcb_poly_from_circle(pin->X, pin->Y, t); + arc = pcb_poly_from_circle(pin->X, pin->Y, pin->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(pin->X - t * 2, pin->X + t * 2, pin->Y - w, pin->Y + w); + pcb_polyarea_boolean_free(m, pa, &arc, PCB_PBO_SUB); + pa = pcb_poly_from_rect(pin->X - w, pin->X + w, pin->Y - t * 2, pin->Y + t * 2); + } + else { + /* t is the theoretically required length, but we use twice that + * to avoid discretisation errors in our circle approximation. + */ + pa = diag_line(pin->X, pin->Y, t * 2, w, pcb_true); + pcb_polyarea_boolean_free(m, pa, &arc, PCB_PBO_SUB); + pa = diag_line(pin->X, pin->Y, t * 2, w, pcb_false); + } + pcb_polyarea_boolean_free(arc, pa, &m, PCB_PBO_SUB); + return m; + } + + + default: + a.X = pin->X; + a.Y = pin->Y; + a.Height = a.Width = pin->Thickness / 2 + pin->Clearance / 4; + a.Thickness = 1; + a.Clearance = pin->Clearance / 2; + a.Flags = pcb_no_flags(); + a.Delta = 90 - (a.Clearance * (1. + 2. * pcb->ThermScale) * 180) / (M_PI * a.Width); + a.StartAngle = 90 - a.Delta / 2 + (style == 4 ? 0 : 45); + pa = pcb_poly_from_arc(&a, a.Clearance); + if (!pa) + return NULL; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->f = arc; + arc->b = pa; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->f->f = arc; + arc->b = pa->f; + a.StartAngle += 90; + arc = pcb_poly_from_arc(&a, a.Clearance); + if (!arc) + return NULL; + pa->b = arc; + pa->f->f->f = arc; + arc->b = pa->f->f; + arc->f = pa; + pa->b = arc; + return pa; + } +} Index: tags/1.2.3/src/obj_pinvia_therm.h =================================================================== --- tags/1.2.3/src/obj_pinvia_therm.h (nonexistent) +++ tags/1.2.3/src/obj_pinvia_therm.h (revision 8969) @@ -0,0 +1,44 @@ +/* + * 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., 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 + * + */ + +/* prototypes for thermal routines + * + * 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_THERMAL_H +#define PCB_THERMAL_H + +#include +#include "config.h" + +pcb_polyarea_t *ThermPoly(pcb_board_t *, pcb_pin_t *, pcb_cardinal_t); + +#endif Index: tags/1.2.3/src/obj_poly.c =================================================================== --- tags/1.2.3/src/obj_poly.c (nonexistent) +++ tags/1.2.3/src/obj_poly.c (revision 8969) @@ -0,0 +1,761 @@ +/* + * 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 + * + */ + +/* Drawing primitive: polygons */ + + +#include "config.h" + +#include "board.h" +#include "data.h" +#include "compat_nls.h" +#include "undo.h" +#include "polygon.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" + +/* 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_polygon_t *pcb_poly_alloc(pcb_layer_t * layer) +{ + pcb_polygon_t *new_obj; + + new_obj = calloc(sizeof(pcb_polygon_t), 1); + polylist_append(&layer->Polygon, new_obj); + + return new_obj; +} + +void pcb_poly_free(pcb_polygon_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_polygon_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_polygon_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_polygon_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_polygon_t, polygon); +} + +/*** utility ***/ + +/* rotates a polygon in 90 degree steps */ +void pcb_poly_rotate90(pcb_polygon_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; + pcb_box_rotate90(&Polygon->BoundingBox, X, Y, Number); +} + +void pcb_poly_rotate(pcb_layer_t *layer, pcb_polygon_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_polygon_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); +} + +void pcb_poly_flip_side(pcb_layer_t *layer, pcb_polygon_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_polygon_t *Polygon) +{ + Polygon->BoundingBox.X1 = Polygon->BoundingBox.Y1 = PCB_MAX_COORD; + Polygon->BoundingBox.X2 = Polygon->BoundingBox.Y2 = 0; + 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_polygon_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_flag_t Flags) +{ + pcb_polygon_t *polygon = pcb_poly_new(Layer, 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_polygon_on_layer(Layer, polygon); + return (polygon); +} + +void pcb_add_polygon_on_layer(pcb_layer_t *Layer, pcb_polygon_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); +} + +/* creates a new polygon on a layer */ +pcb_polygon_t *pcb_poly_new(pcb_layer_t *Layer, pcb_flag_t Flags) +{ + pcb_polygon_t *polygon = pcb_poly_alloc(Layer); + + /* copy values */ + polygon->Flags = Flags; + polygon->ID = pcb_create_ID_get(); + polygon->Clipped = NULL; + polygon->NoHoles = NULL; + polygon->NoHolesValid = 0; + return (polygon); +} + +/* creates a new point in a polygon */ +pcb_point_t *pcb_poly_point_new(pcb_polygon_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_polygon_t *pcb_poly_hole_new(pcb_polygon_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_polygon_t *pcb_poly_copy(pcb_polygon_t *Dest, pcb_polygon_t *Src) +{ + 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, Src->Points[n].Y); + } + 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_polygon_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 *AddPolygonToBuffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + pcb_layer_t *layer = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, Layer)]; + pcb_polygon_t *polygon; + + polygon = pcb_poly_new(layer, Polygon->Flags); + pcb_poly_copy(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 *MovePolygonToBuffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_polygon_t * polygon) +{ + pcb_layer_t *lay = &ctx->buffer.dst->Layer[pcb_layer_id(ctx->buffer.src, layer)]; + + 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); + return (polygon); +} + +/* Handle attempts to change the clearance of a polygon. */ +void *ChangePolygonClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_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 *ChangePolyClear(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Polygon)) + return (NULL); + pcb_undo_add_obj_to_clear_poly(PCB_TYPE_POLYGON, Layer, Polygon, Polygon, pcb_true); + pcb_undo_add_obj_to_flag(PCB_TYPE_POLYGON, Layer, Polygon, Polygon); + PCB_FLAG_TOGGLE(PCB_FLAG_CLEARPOLY, Polygon); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + DrawPolygon(Layer, Polygon); + return (Polygon); +} + +/* inserts a point into a polygon */ +void *InsertPointIntoPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + pcb_point_t save; + pcb_cardinal_t n; + pcb_line_t line; + + 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 + */ + ErasePolygon(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_POLYGON_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)) { + DrawPolygon(Layer, Polygon); + pcb_draw(); + } + return (&Polygon->Points[ctx->insert.idx]); +} + +/* low level routine to move a polygon */ +void pcb_poly_move(pcb_polygon_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 *MovePolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + if (Layer->On) { + ErasePolygon(Polygon); + } + pcb_r_delete_entry(Layer->polygon_tree, (pcb_box_t *) Polygon); + pcb_poly_move(Polygon, ctx->move.dx, ctx->move.dy); + pcb_r_insert_entry(Layer->polygon_tree, (pcb_box_t *) Polygon, 0); + pcb_poly_init_clip(PCB->Data, Layer, Polygon); + if (Layer->On) { + DrawPolygon(Layer, Polygon); + pcb_draw(); + } + return (Polygon); +} + +/* moves a polygon-point */ +void *MovePolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon, pcb_point_t *Point) +{ + if (Layer->On) { + ErasePolygon(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->On) { + DrawPolygon(Layer, Polygon); + pcb_draw(); + } + return (Point); +} + +/* moves a polygon between layers; lowlevel routines */ +void *MovePolygonToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_polygon_t * polygon, pcb_layer_t * Destination) +{ + pcb_r_delete_entry(Source->polygon_tree, (pcb_box_t *) 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); + + return polygon; +} + +struct mptlc { + pcb_layer_id_t snum, dnum; + int type; + pcb_polygon_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(PCB_TYPE_PIN, pin->Element, pin, pin); + else + pcb_undo_add_obj_to_flag(PCB_TYPE_VIA, pin, pin, 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 *MovePolygonToLayer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_polygon_t * Polygon) +{ + pcb_polygon_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 (((long int) ctx->move.dst_layer == -1) || (Layer == ctx->move.dst_layer)) + return (Polygon); + pcb_undo_add_obj_to_move_to_layer(PCB_TYPE_POLYGON, Layer, Polygon, Polygon); + if (Layer->On) + ErasePolygon(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_polygon_s *) MovePolygonToLayerLowLevel(ctx, Layer, Polygon, ctx->move.dst_layer); + pcb_poly_init_clip(PCB->Data, ctx->move.dst_layer, newone); + if (ctx->move.dst_layer->On) { + DrawPolygon(ctx->move.dst_layer, newone); + pcb_draw(); + } + return (newone); +} + + +/* destroys a polygon from a layer */ +void *DestroyPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_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 *DestroyPolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_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; + + 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 RemovePolygonContour(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); + return (Polygon); +} + +/* removes a polygon from a layer */ +void *RemovePolygon_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + /* erase from screen */ + if (Layer->On) { + ErasePolygon(Polygon); + if (!ctx->remove.bulk) + pcb_draw(); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_POLYGON, Layer, Polygon, Polygon); + return NULL; +} + +void *pcb_poly_remove(pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + pcb_opctx_t ctx; + + ctx.remove.pcb = PCB; + ctx.remove.bulk = pcb_false; + ctx.remove.destroy_target = NULL; + + return RemovePolygon_op(&ctx, Layer, Polygon); +} + +/* Removes a contour from a polygon. + If removing the outer contour, it removes the whole polygon. */ +void *RemovePolygonContour(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_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); + + if (Layer->On) { + ErasePolygon(Polygon); + if (!ctx->remove.bulk) + pcb_draw(); + } + + /* Copy the polygon to the undo list */ + pcb_undo_add_obj_to_remove_contour(PCB_TYPE_POLYGON, 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); + /* redraw polygon if necessary */ + if (Layer->On) { + DrawPolygon(Layer, Polygon); + if (!ctx->remove.bulk) + pcb_draw(); + } + return NULL; +} + +/* removes a polygon-point from a polygon */ +void *RemovePolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_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; + + 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 RemovePolygonContour(ctx, Layer, Polygon, contour); + + if (Layer->On) + ErasePolygon(Polygon); + + /* insert the polygon-point into the undo list */ + pcb_undo_add_obj_to_remove_point(PCB_TYPE_POLYGON_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->On) { + DrawPolygon(Layer, Polygon); + if (!ctx->remove.bulk) + pcb_draw(); + } + return NULL; +} + +/* copies a polygon */ +void *CopyPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + pcb_polygon_t *polygon; + + polygon = pcb_poly_new(Layer, pcb_no_flags()); + pcb_poly_copy(polygon, Polygon); + pcb_poly_move(polygon, ctx->copy.DeltaX, ctx->copy.DeltaY); + 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); + DrawPolygon(Layer, polygon); + pcb_undo_add_obj_to_create(PCB_TYPE_POLYGON, Layer, polygon, polygon); + return (polygon); +} + +/*** draw ***/ +pcb_r_dir_t draw_poly_callback(const pcb_box_t * b, void *cl) +{ + pcb_draw_info_t *i = cl; + pcb_polygon_t *polygon = (pcb_polygon_t *) b; + static const char *color; + char buf[sizeof("#XXXXXX")]; + + if (!polygon->Clipped) + return PCB_R_DIR_NOT_FOUND; + + if (PCB_FLAG_TEST(PCB_FLAG_WARN, polygon)) + color = conf_core.appearance.color.warn; + else if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) + color = i->layer->SelectedColor; + 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 + color = i->layer->Color; + pcb_gui->set_color(Output.fgGC, color); + + if ((pcb_gui->thindraw_pcb_polygon != NULL) && (conf_core.editor.thin_draw || conf_core.editor.thin_draw_poly)) + pcb_gui->thindraw_pcb_polygon(Output.fgGC, polygon, i->drawn_area); + else + pcb_gui->fill_pcb_polygon(Output.fgGC, polygon, i->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_polygon_t poly = *polygon; + + for (poly.Clipped = polygon->Clipped->f; poly.Clipped != polygon->Clipped; poly.Clipped = poly.Clipped->f) + pcb_gui->thindraw_pcb_polygon(Output.fgGC, &poly, i->drawn_area); + } + + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a polygon on a layer */ +void ErasePolygon(pcb_polygon_t *Polygon) +{ + pcb_draw_invalidate(Polygon); + pcb_flag_erase(&Polygon->Flags); +} + +void DrawPolygon(pcb_layer_t *Layer, pcb_polygon_t *Polygon) +{ + pcb_draw_invalidate(Polygon); +} Index: tags/1.2.3/src/obj_poly.h =================================================================== --- tags/1.2.3/src/obj_poly.h (nonexistent) +++ tags/1.2.3/src/obj_poly.h (revision 8969) @@ -0,0 +1,121 @@ +/* + * 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 + * + */ + +/* Drawing primitive: polygons */ + +#ifndef PCB_OBJ_POLY_H +#define PCB_OBJ_POLY_H + +#include "obj_common.h" +#include "polyarea.h" + +struct pcb_polygon_s { /* holds information about a polygon */ + PCB_ANYOBJECTFIELDS; + 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_polygon_t *pcb_poly_alloc(pcb_layer_t * layer); +void pcb_poly_free(pcb_polygon_t * data); +pcb_point_t *pcb_poly_point_alloc(pcb_polygon_t *Polygon); +pcb_cardinal_t *pcb_poly_holeidx_new(pcb_polygon_t *Polygon); +void pcb_poly_free_fields(pcb_polygon_t * polygon); + +void pcb_poly_bbox(pcb_polygon_t *Polygon); +pcb_polygon_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_flag_t Flags); +pcb_polygon_t *pcb_poly_new(pcb_layer_t *Layer, pcb_flag_t Flags); +pcb_point_t *pcb_poly_point_new(pcb_polygon_t *Polygon, pcb_coord_t X, pcb_coord_t Y); +pcb_polygon_t *pcb_poly_hole_new(pcb_polygon_t * Polygon); +void *pcb_poly_remove(pcb_layer_t *Layer, pcb_polygon_t *Polygon); + +void pcb_poly_rotate90(pcb_polygon_t *Polygon, pcb_coord_t X, pcb_coord_t Y, unsigned Number); +void pcb_poly_rotate(pcb_layer_t *layer, pcb_polygon_t *poly, pcb_coord_t X, pcb_coord_t Y, double cosa, double sina); +void pcb_poly_mirror(pcb_layer_t *layer, pcb_polygon_t *polygon); +void pcb_poly_flip_side(pcb_layer_t *layer, pcb_polygon_t *polygon); + +void pcb_poly_move(pcb_polygon_t *Polygon, pcb_coord_t DX, pcb_coord_t DY); +pcb_polygon_t *pcb_poly_copy(pcb_polygon_t *Dest, pcb_polygon_t *Src); + +/* Add objects without creating them or making any "sanity modifications" to them */ +void pcb_add_polygon_on_layer(pcb_layer_t *Layer, pcb_polygon_t *polygon); + +double pcb_poly_area(const pcb_polygon_t *poly); + +#define PCB_POLY_LOOP(layer) do { \ + pcb_polygon_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->On) \ + PCB_POLY_LOOP(layer) + + +#endif Index: tags/1.2.3/src/obj_poly_draw.h =================================================================== --- tags/1.2.3/src/obj_poly_draw.h (nonexistent) +++ tags/1.2.3/src/obj_poly_draw.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard draw of polygons ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_poly_callback(const pcb_box_t * b, void *cl); +#endif + +void ErasePolygon(pcb_polygon_t *Polygon); +void DrawPolygon(pcb_layer_t *Layer, pcb_polygon_t *Polygon); Index: tags/1.2.3/src/obj_poly_list.c =================================================================== --- tags/1.2.3/src/obj_poly_list.c (nonexistent) +++ tags/1.2.3/src/obj_poly_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_poly_list.h" +#include Index: tags/1.2.3/src/obj_poly_list.h =================================================================== --- tags/1.2.3/src/obj_poly_list.h (nonexistent) +++ tags/1.2.3/src/obj_poly_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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_polygon_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.3/src/obj_poly_op.h =================================================================== --- tags/1.2.3/src/obj_poly_op.h (nonexistent) +++ tags/1.2.3/src/obj_poly_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on polygons ***/ + +#include "operation.h" + +void *AddPolygonToBuffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *MovePolygonToBuffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_polygon_t * polygon); +void *ChangePolygonClearSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *poly); +void *ChangePolyClear(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *InsertPointIntoPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *MovePolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *MovePolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon, pcb_point_t *Point); +void *MovePolygonToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_polygon_t * polygon, pcb_layer_t * Destination); +void *MovePolygonToLayer(pcb_opctx_t *ctx, pcb_layer_t * Layer, pcb_polygon_t * Polygon); +void *DestroyPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *DestroyPolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon, pcb_point_t *Point); +void *RemovePolygon_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); +void *RemovePolygonContour(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon, pcb_cardinal_t contour); +void *RemovePolygonPoint(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon, pcb_point_t *Point); +void *CopyPolygon(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_polygon_t *Polygon); + + Index: tags/1.2.3/src/obj_rat.c =================================================================== --- tags/1.2.3/src/obj_rat.c (nonexistent) +++ tags/1.2.3/src/obj_rat.c (revision 8969) @@ -0,0 +1,289 @@ +/* + * 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 + * + */ + +/* 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); + 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; + RemoveRat(&ctx, line); + } + } + PCB_END_LOOP; + if (changed) { + pcb_draw(); + pcb_undo_inc_serial(); + } + return (changed); +} + + +/*** ops ***/ +/* copies a rat-line to paste buffer */ +void *AddRatToBuffer(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 *MoveRatToBuffer(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); + return rat; +} + +/* inserts a point into a rat-line */ +void *InsertPointIntoRat(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); + EraseRat(Rat); + DrawLine(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); + DrawLine(CURRENT, newone); + } + pcb_undo_move_obj_to_remove(PCB_TYPE_RATLINE, Rat, Rat, Rat); + pcb_draw(); + return (newone); +} + +/* moves a line between layers */ +void *MoveRatToLayer(pcb_opctx_t *ctx, pcb_rat_t * Rat) +{ + pcb_line_t *newone; + /*pcb_coord_t X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; + pcb_coord_t X1 = Rat->Point1.X, Y1 = Rat->Point1.Y; + if PCB_FLAG_VIA + if we're on a pin, add a thermal + else make a via and a wire, but 0-length wire not good + else as before */ + + 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) + EraseRat(Rat); + pcb_undo_move_obj_to_remove(PCB_TYPE_RATLINE, Rat, Rat, Rat); + DrawLine(ctx->move.dst_layer, newone); + pcb_draw(); + return (newone); +} + +/* destroys a rat */ +void *DestroyRat(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 *RemoveRat(pcb_opctx_t *ctx, pcb_rat_t *Rat) +{ + /* erase from screen and memory */ + if (PCB->RatOn) { + EraseRat(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 draw_rat_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(Output.fgGC, conf_core.appearance.color.rat_selected); + else + pcb_gui->set_color(Output.fgGC, conf_core.appearance.color.connected); + } + else + pcb_gui->set_color(Output.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) + pcb_gui->set_line_width(Output.fgGC, 0); + else + pcb_gui->set_line_width(Output.fgGC, w); + pcb_gui->draw_arc(Output.fgGC, rat->Point1.X, rat->Point1.Y, w * 2, w * 2, 0, 360); + } + else + _draw_line((pcb_line_t *) rat); + return PCB_R_DIR_FOUND_CONTINUE; +} + +void EraseRat(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 + EraseLine((pcb_line_t *) Rat); + pcb_flag_erase(&Rat->Flags); +} + +void DrawRat(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 + DrawLine(NULL, (pcb_line_t *) Rat); +} Index: tags/1.2.3/src/obj_rat.h =================================================================== --- tags/1.2.3/src/obj_rat.h (nonexistent) +++ tags/1.2.3/src/obj_rat.h (revision 8969) @@ -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., 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 + * + */ + +/* 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.3/src/obj_rat_draw.h =================================================================== --- tags/1.2.3/src/obj_rat_draw.h (nonexistent) +++ tags/1.2.3/src/obj_rat_draw.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard draw on rats ***/ + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_rat_callback(const pcb_box_t * b, void *cl); +#endif + +void EraseRat(pcb_rat_t *Rat); +void DrawRat(pcb_rat_t *Rat); Index: tags/1.2.3/src/obj_rat_list.c =================================================================== --- tags/1.2.3/src/obj_rat_list.c (nonexistent) +++ tags/1.2.3/src/obj_rat_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#define TDL_DONT_UNDEF +#include "obj_rat_list.h" +#include Index: tags/1.2.3/src/obj_rat_list.h =================================================================== --- tags/1.2.3/src/obj_rat_list.h (nonexistent) +++ tags/1.2.3/src/obj_rat_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_rat_op.h =================================================================== --- tags/1.2.3/src/obj_rat_op.h (nonexistent) +++ tags/1.2.3/src/obj_rat_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on rat lines ***/ + +#include "operation.h" + +void *AddRatToBuffer(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *MoveRatToBuffer(pcb_opctx_t *ctx, pcb_rat_t * rat); +void *InsertPointIntoRat(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *MoveRatToLayer(pcb_opctx_t *ctx, pcb_rat_t * Rat); +void *DestroyRat(pcb_opctx_t *ctx, pcb_rat_t *Rat); +void *RemoveRat(pcb_opctx_t *ctx, pcb_rat_t *Rat); Index: tags/1.2.3/src/obj_text.c =================================================================== --- tags/1.2.3/src/obj_text.c (nonexistent) +++ tags/1.2.3/src/obj_text.c (revision 8969) @@ -0,0 +1,742 @@ +/* + * 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 + * + */ + +/* 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" + +/* 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); + 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; + + pcb_add_text_on_layer(Layer, text, PCBFont); + + return (text); +} + +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); + text->ID = pcb_create_ID_get(); + 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); +} + +/* 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 = (unsigned char *) Text->TextString; + 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_polygon_t *poly; + + 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); +} + + + +/*** ops ***/ +/* copies a text to buffer */ +void *AddTextToBuffer(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)]; + + return (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))); +} + +/* moves a text to buffer without allocating memory for the name */ +void *MoveTextToBuffer(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); + return (text); +} + +/* changes the scaling factor of a text object */ +void *ChangeTextSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + int value = ctx->chgsize.absolute ? PCB_COORD_TO_MIL(ctx->chgsize.absolute) + : Text->Scale + PCB_COORD_TO_MIL(ctx->chgsize.delta); + + 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); + EraseText(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); + DrawText(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 *ChangeTextName(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); + EraseText(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); + DrawText(Layer, Text); + return (old); +} + +/* changes the clearance flag of a text */ +void *ChangeTextJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + if (PCB_FLAG_TEST(PCB_FLAG_LOCK, Text)) + return (NULL); + EraseText(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(PCB_TYPE_TEXT, Layer, Text, 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); + } + DrawText(Layer, Text); + return (Text); +} + +/* sets the clearance flag of a text */ +void *SetTextJoin(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 ChangeTextJoin(ctx, Layer, Text); +} + +/* clears the clearance flag of a text */ +void *ClrTextJoin(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 ChangeTextJoin(ctx, Layer, Text); +} + +/* copies a text */ +void *CopyText(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)); + DrawText(Layer, text); + pcb_undo_add_obj_to_create(PCB_TYPE_TEXT, Layer, text, text); + return (text); +} + +/* moves a text object */ +void *MoveText(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_poly_restore_to_poly(PCB->Data, PCB_TYPE_TEXT, Layer, Text); + pcb_r_delete_entry(Layer->text_tree, (pcb_box_t *) Text); + if (Layer->On) { + EraseText(Layer, Text); + pcb_text_move(Text, ctx->move.dx, ctx->move.dy); + DrawText(Layer, Text); + pcb_draw(); + } + else + pcb_text_move(Text, ctx->move.dx, ctx->move.dy); + 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 *MoveTextToLayerLowLevel(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(PCB, pcb_layer_id(PCB->Data, 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); + + return text; +} + +/* moves a text object between layers */ +void *MoveTextToLayer(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->On) + EraseText(layer, text); + text = MoveTextToLayerLowLevel(ctx, layer, text, ctx->move.dst_layer); + if (ctx->move.dst_layer->On) + DrawText(ctx->move.dst_layer, text); + if (layer->On || ctx->move.dst_layer->On) + pcb_draw(); + } + return text; +} + +/* destroys a text from a layer */ +void *DestroyText(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 *RemoveText_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + /* erase from screen */ + if (Layer->On) { + EraseText(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 RemoveText_op(&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_box_rotate90(&Text->BoundingBox, X, Y, 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); +} + +/* rotates a text object and redraws it */ +void *Rotate90Text(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text) +{ + EraseText(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); + DrawText(Layer, Text); + pcb_draw(); + return (Text); +} + +void pcb_text_flip_side(pcb_layer_t *layer, pcb_text_t *text) +{ + 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); + 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); +} + +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_poly_restore_to_poly(PCB->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(PCB->Data, PCB_TYPE_TEXT, layer, text); +} + +/*** draw ***/ + +#define MAX_SIMPLE_POLY_POINTS 256 +static void draw_text_poly(pcb_text_t *Text, pcb_polygon_t *poly, pcb_coord_t x0) +{ + 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; + } + + pcb_gui->fill_polygon(Output.fgGC, poly->PointN, x, y); +} + + +/* --------------------------------------------------------------------------- + * lowlevel drawing routine for text objects + */ +void DrawTextLowLevel(pcb_text_t *Text, pcb_coord_t min_line_width) +{ + pcb_coord_t x = 0; + unsigned char *string = (unsigned char *) Text->TextString; + pcb_cardinal_t n; + pcb_font_t *font = pcb_font(PCB, Text->fid, 1); + + 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_polygon_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; + _draw_line(&newline); + } + + /* 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; + _draw_arc(&newarc); + } + + /* draw the polygons */ + for(p = polylist_first(&font->Symbol[*string].polys); p != NULL; p = polylist_next(p)) + draw_text_poly(Text, p, x); + + /* 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(Output.fgGC, defaultsymbol.X1, defaultsymbol.Y1, defaultsymbol.X2, defaultsymbol.Y2); + + /* move on to next cursor position */ + x += size; + } + string++; + } +} + + +pcb_r_dir_t draw_text_callback(const pcb_box_t * b, void *cl) +{ + pcb_layer_t *layer = cl; + pcb_text_t *text = (pcb_text_t *) b; + int min_silk_line; + unsigned int flg = 0; + + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text)) + pcb_gui->set_color(Output.fgGC, layer->SelectedColor); + else + pcb_gui->set_color(Output.fgGC, layer->Color); + + if (layer->grp >= 0) + flg = pcb_layergrp_flags(PCB, layer->grp); + + if (flg & PCB_LYT_SILK) + min_silk_line = PCB->minSlk; + else + min_silk_line = PCB->minWid; + DrawTextLowLevel(text, min_silk_line); + return PCB_R_DIR_FOUND_CONTINUE; +} + +/* erases a text on a layer */ +void EraseText(pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_draw_invalidate(Text); +} + +void DrawText(pcb_layer_t *Layer, pcb_text_t *Text) +{ + pcb_draw_invalidate(Text); +} + +/*** init ***/ +static const char *text_cookie = "obj_text"; + +static void pcb_text_font_chg(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + pcb_font_id_t fid; + int need_redraw = 0; + + if ((argc < 2) || (argv[1].type != PCB_EVARG_INT)) + return; + + fid = argv[1].d.i; + + LAYER_LOOP(PCB->Data, pcb_max_layer); { + 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(PCB->Data); { + PCB_ELEMENT_PCB_TEXT_LOOP(element); { + if (text->fid == fid) { + pcb_element_text_update(PCB, PCB->Data, element, n); + need_redraw = 1; + } + } PCB_END_LOOP; + } PCB_END_LOOP; + + + if (need_redraw) + 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", fid); +} + +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.3/src/obj_text.h =================================================================== --- tags/1.2.3/src/obj_text.h (nonexistent) +++ tags/1.2.3/src/obj_text.h (revision 8969) @@ -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., 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 + * + */ + +/* 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; + gdl_elem_t link; /* a text is in a list of a layer or an element */ +}; + + +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); +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); +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); + + +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)->On) + +#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.3/src/obj_text_draw.h =================================================================== --- tags/1.2.3/src/obj_text_draw.h (nonexistent) +++ tags/1.2.3/src/obj_text_draw.h (revision 8969) @@ -0,0 +1,37 @@ +/* + * 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 + * + */ + +/*** Standard draw of text ***/ + + +/* Include rtree.h for these */ +#ifdef PCB_RTREE_H +pcb_r_dir_t draw_text_callback(const pcb_box_t * b, void *cl); +#endif + +void DrawTextLowLevel(pcb_text_t *Text, pcb_coord_t min_line_width); +void EraseText(pcb_layer_t *Layer, pcb_text_t *Text); +void DrawText(pcb_layer_t *Layer, pcb_text_t *Text); Index: tags/1.2.3/src/obj_text_list.c =================================================================== --- tags/1.2.3/src/obj_text_list.c (nonexistent) +++ tags/1.2.3/src/obj_text_list.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_text_list.h =================================================================== --- tags/1.2.3/src/obj_text_list.h (nonexistent) +++ tags/1.2.3/src/obj_text_list.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/obj_text_op.h =================================================================== --- tags/1.2.3/src/obj_text_op.h (nonexistent) +++ tags/1.2.3/src/obj_text_op.h (revision 8969) @@ -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., 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 + * + */ + +/*** Standard operations on text ***/ + +#include "operation.h" + +void *AddTextToBuffer(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *MoveTextToBuffer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text); +void *ChangeTextSize(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *ChangeTextName(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *ChangeTextJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *SetTextJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *ClrTextJoin(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *CopyText(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *MoveText(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *MoveTextToLayerLowLevel(pcb_opctx_t *ctx, pcb_layer_t * Source, pcb_text_t * text, pcb_layer_t * Destination); +void *MoveTextToLayer(pcb_opctx_t *ctx, pcb_layer_t * layer, pcb_text_t * text); +void *DestroyText(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *RemoveText_op(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); +void *Rotate90Text(pcb_opctx_t *ctx, pcb_layer_t *Layer, pcb_text_t *Text); Index: tags/1.2.3/src/object_act.c =================================================================== --- tags/1.2.3/src/object_act.c (nonexistent) +++ tags/1.2.3/src/object_act.c (revision 8969) @@ -0,0 +1,1223 @@ +/* + * 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 "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" + +/* --------------------------------------------------------------------------- */ + +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; +} + +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; +} + +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)\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."; + +/* %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; + } + } + buf = (char *) malloc(strlen(layer->Name) + strlen("Layer X Attributes")); + sprintf(buf, "Layer %s Attributes", layer->Name); + pcb_gui->edit_attributes(buf, &(layer->Attributes)); + free(buf); + 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; + } + + 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 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_ELEMENT_LOOP(PCB->Data); + { + /* + * If we want to disperse selected elements, 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 + */ + if (!PCB_FLAG_TEST(PCB_FLAG_LOCK, element) && (all || PCB_FLAG_TEST(PCB_FLAG_SELECTED, element))) { + + /* figure out how much to move the element */ + dx = minx - element->BoundingBox.X1; + + /* snap to the grid */ + dx -= (element->MarkX + 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 + element->BoundingBox.X2 + dx > PCB->MaxWidth) { + miny = maxy + GAP; + minx = GAP; + } + + /* figure out how much to move the element */ + dx = minx - element->BoundingBox.X1; + dy = miny - element->BoundingBox.Y1; + + /* snap to the grid */ + dx -= (element->MarkX + dx) % PCB->Grid; + dx += PCB->Grid; + dy -= (element->MarkY + dy) % PCB->Grid; + dy += PCB->Grid; + + /* 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); + + /* keep track of how tall this row is */ + minx += element->BoundingBox.X2 - element->BoundingBox.X1 + GAP; + if (maxy < element->BoundingBox.Y2) { + maxy = element->BoundingBox.Y2; + } + } + + } + PCB_END_LOOP; + + /* 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(); + } + break; + case F_Selected: + case F_SelectedElements: + pcb_undo_save_serial(); + 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, &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 pcb_act_ElementList(int argc, const char **argv, pcb_coord_t x, pcb_coord_t y) +{ + pcb_element_t *e = NULL; + 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); + + if (!e) { + 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) { +#ifdef DEBUG + printf(" ... Footprint on board, but different from footprint loaded.\n"); +#endif + int er, pr, i; + pcb_coord_t mx, my; + pcb_element_t *pe; + + /* Different footprint, we need to swap them out. */ + if (pcb_act_LoadFootprint(argc, args, x, y)) { + number_of_footprints_not_found++; + return 1; + } + + er = pcb_element_get_orientation(e); + pe = elementlist_first(&(PCB_PASTEBUFFER->Data->Element)); + if (!PCB_FRONT(e)) + pcb_element_mirror(PCB_PASTEBUFFER->Data, pe, pe->MarkY * 2 - PCB->MaxHeight); + pr = pcb_element_get_orientation(pe); + + mx = e->MarkX; + my = e->MarkY; + + if (er != pr) + pcb_element_rotate90(PCB_PASTEBUFFER->Data, pe, pe->MarkX, pe->MarkY, (er - pr + 4) % 4); + + for (i = 0; i < PCB_MAX_ELEMENTNAMES; i++) { + pe->Name[i].X = e->Name[i].X - mx + pe->MarkX; + pe->Name[i].Y = e->Name[i].Y - my + pe->MarkY; + pe->Name[i].Direction = e->Name[i].Direction; + pe->Name[i].Scale = e->Name[i].Scale; + } + + pcb_element_remove(e); + + if (pcb_buffer_copy_to_layout(PCB, mx, my)) + pcb_board_set_changed_flag(pcb_true); + } + + /* Now reload footprint */ + element_cache = NULL; + e = find_element_by_refdes(refdes); + + 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); + +#ifdef DEBUG + printf(" ... Leaving pcb_act_ElementList.\n"); +#endif + + return 0; +} + +/* ---------------------------------------------------------------- */ +static const char pcb_acts_ElementSetAttr[] = "ElementSetAttr(refdes,name[,value])"; + +static const char pcb_acth_ElementSetAttr[] = "Sets or clears an element-specific attribute."; + +/* %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; + 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); + + 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, 0); + } + + 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; + + if (pcb_search_screen(pcb_crosshair.X, pcb_crosshair.Y, PCB_TYPE_ELEMENT, &ptr1, &ptr2, &ptr3) != PCB_TYPE_NONE) { + 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(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; + 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; + 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 < 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 < 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; + + 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; + int new_top = -1; + + 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(-1, 0, pcb_actd_EditGroup_gid); + } + else if (strcmp(argv[1], "ga") == 0) { + return pcb_layer_move(-1, 1, pcb_actd_EditGroup_gid); + } + else if (strcmp(argv[1], "up") == 0) { + new_index = INDEXOFCURRENT - 1; + if (new_index < 0) + return 1; + new_top = new_index; + } + else if (strcmp(argv[1], "down") == 0) { + new_index = INDEXOFCURRENT + 1; + if (new_index >= pcb_max_layer) + return 1; + new_top = new_index; + } + else if (strncmp(argv[1], "step", 4) == 0) { + pcb_layer_t *l = CURRENT; + pcb_layer_group_t *g = pcb_get_layergrp(PCB, l->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(g, pcb_layer_id(PCB->Data, l), +1); break; + case '-': return pcb_layergrp_step_layer(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(old_index); + pcb_layer_group_t *g = pcb_get_layergrp(PCB, l->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(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(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.3/src/operation.h =================================================================== --- tags/1.2.3/src/operation.h (nonexistent) +++ tags/1.2.3/src/operation.h (revision 8969) @@ -0,0 +1,128 @@ +/* + * 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_coord_t delta; /* change of size */ + pcb_coord_t absolute; /* Absolute size */ +} pcb_opctx_chgsize_t; + +typedef struct { + pcb_board_t *pcb; + int is_primary; /* whether the primary parameter should be changed */ + pcb_angle_t delta, absolute; /* 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; +} pcb_opctx_chgtherm_t; + +typedef struct { + pcb_board_t *pcb; + pcb_coord_t DeltaX, DeltaY; /* movement vector */ +} 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 */ +} pcb_opctx_rotate_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_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_polygon_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_polygon_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); +} pcb_opfunc_t; + +#endif Index: tags/1.2.3/src/paths.c =================================================================== --- tags/1.2.3/src/paths.c (nonexistent) +++ tags/1.2.3/src/paths.c (revision 8969) @@ -0,0 +1,201 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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); + + +void pcb_paths_resolve(const char **in, char **out, int numpaths, unsigned int extra_room) +{ + const char *subst_to; + int subst_offs; + for (; numpaths > 0; numpaths--, in++, out++) { + if (*in != NULL) { + if (**in == '~') { + int l1, l2; + if (conf_core.rc.path.home == NULL) { + pcb_message(PCB_MSG_ERROR, "can't resolve home dir required for path %s\n", *in); + exit(1); + } + subst_to = conf_core.rc.path.home; + subst_offs = 1; + replace:; + /* avoid pcb_concat() here to reduce dependencies for external tools */ + l1 = strlen(subst_to); + l2 = strlen((*in) + 1); + *out = malloc(l1 + l2 + 4 + extra_room); + sprintf(*out, "%s%s", subst_to, (*in) + subst_offs); + } + else if (**in == '$') { + if ((*in)[1] == '(') { + char *end = strchr((*in)+2, ')'); + if (end != NULL) { + char hash_path[128]; + int len = end - (*in); + if (len < sizeof(hash_path)-1) { + conf_native_t *cn; + const char *si; + char *so; + int n; + + (*in) += 2; + len -= 2; + for(si = *in, so = hash_path, n=0; n < len; n++,si++,so++) { + if (*si == '.') + *so = '/'; + else + *so = *si; + } + *so = 0; + cn = conf_get_field(hash_path); + if ((cn != NULL) && (cn->type == CFN_STRING)) { + subst_to = cn->val.string[0]; + subst_offs = len+1; + goto replace; + } + } + } + pcb_message(PCB_MSG_WARNING, "can't resolve conf-hash dir required for path %s\n", *in); + *out = NULL; + } + else + *out = NULL; + } + else { + *out = malloc(strlen(*in) + 1 + extra_room); + strcpy(*out, *in); + } + } + else + *out = NULL; + } +} + +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; +} + +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); +} + +char *pcb_build_argfn(const char *template, pcb_build_argfn_t *arg) +{ + return pcb_strdup_subst(template, pcb_build_argfn_cb, arg); +} Index: tags/1.2.3/src/paths.h =================================================================== --- tags/1.2.3/src/paths.h (nonexistent) +++ tags/1.2.3/src/paths.h (revision 8969) @@ -0,0 +1,76 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2016 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/pcb-conf.lht =================================================================== --- tags/1.2.3/src/pcb-conf.lht (nonexistent) +++ tags/1.2.3/src/pcb-conf.lht (revision 8969) @@ -0,0 +1,283 @@ +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 = 110 + buffer_number = 0 + clear_line = 1 + full_poly = 0 + unique_names = 0 + 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 + local_ref = 0 + check_planes = 0 + hide_names = 0 + description = 0 + name_on_pcb = 0 + 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 +# font_command = {} +# file_command = {} +# file_path = {} + library_shell = {} + + emergency_name = {PCB.%ld.save} + backup_name = {PCB.%P.backup} + + 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 = { + {./default.pcb} + {$(rc.path.share)/default.pcb} + } + +# script_filename = {} +# action_string = {} +# rat_path = {} +# rat_command = {} + li:preferred_gui = { gtk2_gl; gtk2_gdk; lesstif } + save_final_fallback_fmt = lihata + } # 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} + 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: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.3/src/pcb-menu-gtk.lht =================================================================== --- tags/1.2.3/src/pcb-menu-gtk.lht (nonexistent) +++ tags/1.2.3/src/pcb-menu-gtk.lht (revision 8969) @@ -0,0 +1,662 @@ +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 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 hyp = { action=LoadHypFrom() } + } + } + - + ha:Save connection data of { + li:submenu { + ha:a single element = { li:action={ GetXY(Click to set the element mark <>); 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:Change flags { + li:submenu { + ha:Nonetlist = { a=Altn; action=ChangeNonetlist(Element) } + } + } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + } + } # 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 = { li: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 Names = { checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only Names = { checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide Names = { 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 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: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: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 = { action=DisperseElements(All) } + ha:Disperse selected elements = { 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: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:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements to file = { action=Save(PasteBuffer) } + - + 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={Shift=}; 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: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.3/src/pcb-menu-lesstif.lht =================================================================== --- tags/1.2.3/src/pcb-menu-lesstif.lht (nonexistent) +++ tags/1.2.3/src/pcb-menu-lesstif.lht (revision 8969) @@ -0,0 +1,521 @@ +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 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 hyp = { 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 = { li:action={GetXY(Click to set the element mark <>); 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 Names = { checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only Names = { checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide Names = { 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 = { li: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 text 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:Board Sizes = { action=AdjustSizes() } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + } + } # 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: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: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 = { 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: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:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements to file = { action=Save(PasteBuffer) } + - + 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={Shift=}; 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.3/src/pcb-menu-mkey.lht =================================================================== --- tags/1.2.3/src/pcb-menu-mkey.lht (nonexistent) +++ tags/1.2.3/src/pcb-menu-mkey.lht (revision 8969) @@ -0,0 +1,625 @@ +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 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 hyp = { action=LoadHypFrom() } + } + } + - + ha:Save connection data of { + li:submenu { + ha:a single element = { li:action={ GetXY(Click to set the element mark <>); 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(AddSelected); RemoveSelected(); 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:Change flags { + li:submenu { + ha:Nonetlist = { a=Altn; action=ChangeNonetlist(Element) } + } + } + ha:Route Styles { + li:submenu { + @routestyles + - + ha:Edit... = { action=AdjustStyle(0) } + } + } + } + } # 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 = { li: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 Names = { checked=editor/lock_names; action=conf(toggle, editor/lock_names, design) } + ha:Only Names = { checked=editor/only_names; action=conf(toggle, editor/only_names, design) } + ha:Hide Names = { 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: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: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 = { action=DisperseElements(All) } + ha:Disperse selected elements = { 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: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:Break buffer elements to pieces = { action=PasteBuffer(Restore) } + ha:Save buffer elements to file = { action=Save(PasteBuffer) } + - + 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={Shift=}; 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.3/src/pcb-printf.c =================================================================== --- tags/1.2.3/src/pcb-printf.c (nonexistent) +++ tags/1.2.3/src/pcb-printf.c (revision 8969) @@ -0,0 +1,899 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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; + + 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 ((Units[n].allow & allow) != 0 && (Units[n].family == family)) { + int n_above_one = 0; + + for (i = 0; i < n_coords; ++i) + if (abs(value[i] * 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 ((Units[n].allow & allow) == 0 || Units[n].family != family); + } + + /* Apply scale factor */ + suffix = Units[n].suffix; + for (i = 0; i < n_coords; ++i) + value[i] = value[i] * Units[n].scale_factor; + + make_printf_spec(printf_spec_new, printf_spec, 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; +} + +/* \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; + char tmp[128]; /* large enough for rendering a long long int */ + int tmplen, retval = -1, slot_recursion = 0; + char *dot, *free_fmt = NULL; + enum pcb_allow_e mask = PCB_UNIT_ALLOW_ALL; + + 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); + + /* 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 == '[') { + 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; + } + 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') { +#if 0 +/* C89 does not have long long int - best to avoid %lld */ + if (spec.array[2] == 'l') + tmplen = sprintf(tmp, spec.array, va_arg(args, long long)); + else +#endif + 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') + value[0] = va_arg(args, pcb_coord_t); + count = 1; + switch (*fmt) { + 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, mask & 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, 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, Units[i].suffix) == 0) { + if (CoordsToString(string, value, 1, &spec, Units[i].allow, suffix) != 0) goto err; + found = 1; + break; + } + } + if (!found) + if (CoordsToString(string, value, 1, &spec, mask & PCB_UNIT_ALLOW_ALL, 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 == Units[i].printf_code) { + if (CoordsToString(string, value, 1, &spec, Units[i].allow, suffix) != 0) goto err; + found = 1; + break; + } + } + if (!found) + if (CoordsToString(string, value, 1, &spec, PCB_UNIT_ALLOW_ALL, 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; +} + + +char *pcb_strdup_subst(const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx) +{ + gds_t s; + const char *curr, *next; + + gds_init(&s); + for(curr = template;;) { + next = strchr(curr, '%'); + if (next == NULL) { + gds_append_str(&s, curr); + return s.array; + } + if (next > curr) + gds_append_len(&s, curr, next-curr); + 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; + } + } + abort(); /* can't get here */ +} Index: tags/1.2.3/src/pcb-printf.h =================================================================== --- tags/1.2.3/src/pcb-printf.h (nonexistent) +++ tags/1.2.3/src/pcb-printf.h (revision 8969) @@ -0,0 +1,127 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 specifiers are: + * %mI outout 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) + * %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. + * + * 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 template; also 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. +*/ +char *pcb_strdup_subst(const char *template, int (*cb)(void *ctx, gds_t *s, const char **input), void *ctx); + +#endif Index: tags/1.2.3/src/pcb_bool.c =================================================================== --- tags/1.2.3/src/pcb_bool.c (nonexistent) +++ tags/1.2.3/src/pcb_bool.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/pcb_bool.h =================================================================== --- tags/1.2.3/src/pcb_bool.h (nonexistent) +++ tags/1.2.3/src/pcb_bool.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/plug_footprint.c =================================================================== --- tags/1.2.3/src/plug_footprint.c (nonexistent) +++ tags/1.2.3/src/plug_footprint.c (revision 8969) @@ -0,0 +1,444 @@ +/* + * 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 + * + */ + +#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; + } +} + +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, 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->fclose != NULL)) + fctx->backend->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[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; + + /* Initialize path, working by writing 0 into every byte. */ + memset(toppath, 0, sizeof toppath); + + /* 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)) { + /* remove trailing path delimiter */ + strncpy(toppath, p, sizeof(toppath) - 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 + 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.3/src/plug_footprint.h =================================================================== --- tags/1.2.3/src/plug_footprint.h (nonexistent) +++ tags/1.2.3/src/plug_footprint.h (revision 8969) @@ -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 *(*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 (*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.3/src/plug_footprint_act.c =================================================================== --- tags/1.2.3/src/plug_footprint_act.c (nonexistent) +++ tags/1.2.3/src/plug_footprint_act.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/plug_import.c =================================================================== --- tags/1.2.3/src/plug_import.c (nonexistent) +++ tags/1.2.3/src/plug_import.c (revision 8969) @@ -0,0 +1,117 @@ +/* + * 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., 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 + * + */ + +/* 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" + + +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 = 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.3/src/plug_import.h =================================================================== --- tags/1.2.3/src/plug_import.h (nonexistent) +++ tags/1.2.3/src/plug_import.h (revision 8969) @@ -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., 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 + * + */ + +#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.3/src/plug_io.c =================================================================== --- tags/1.2.3/src/plug_io.c (nonexistent) +++ tags/1.2.3/src/plug_io.c (revision 8969) @@ -0,0 +1,964 @@ +/* + * 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., 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 + * + */ + + +/* 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" + +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + +#include "config.h" +#include "conf_core.h" + +#include +#include +#include +#include +#include + +#include "change.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 "layer_vis.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 = 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); + } +} + +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 = 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 */ + 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 (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; + 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)) + return n; + } + } + } + /* 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) +{ + 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); + 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) + 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; + + 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); + pcb_layervis_reset_stack(); + + 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); + } + + /* 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; + } + + /* 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); + } + + 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 = 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); + 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_gui->notify_save_pcb(file, pcb_false); + retcode = pcb_write_pipe(file, pcb_true, fmt); + 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')) { + 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, DEFAULT_FMT, pcb_true); + } +} + +/* --------------------------------------------------------------------------- + * 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; + + 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); + } + } + + pcb_write_pcb_file(filename, pcb_true, NULL, pcb_true); + 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); + 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) +{ + 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); +} + +/* --------------------------------------------------------------------------- + * writes PCB to file + */ +int pcb_write_pcb_file(const char *Filename, pcb_bool thePcb, const char *fmt, pcb_bool emergency) +{ + 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 (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 = fopen(Filename, "w")) == NULL) { + pcb_open_error_message(Filename); + return (-1); + } + + result = pcb_write_file(fp, thePcb, fn_tmp, Filename, fmt, emergency); + + 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) +{ + FILE *fp; + int result; + const char *p; + static gds_t command; + + if (PCB_EMPTY_STRING_P(conf_core.rc.save_command)) + return pcb_write_pcb_file(Filename, thePcb, fmt, pcb_false); + + /* setup commandline */ + gds_truncate(&command,0); + for (p = conf_core.rc.save_command; *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 = popen(command.array, "w")) == NULL) { + pcb_popen_error_message(command.array); + return (-1); + } + + result = pcb_write_file(fp, thePcb, NULL, NULL, fmt, pcb_false); + + return (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; + } + } +} Index: tags/1.2.3/src/plug_io.h =================================================================== --- tags/1.2.3/src/plug_io.h (nonexistent) +++ tags/1.2.3/src/plug_io.h (revision 8969) @@ -0,0 +1,183 @@ +/* + * 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., 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 + * + */ + +#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); + + /* 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); +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); +int pcb_write_pipe(const char *, pcb_bool, const char *fmt); + +#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); + +#endif Index: tags/1.2.3/src/plugins.c =================================================================== --- tags/1.2.3/src/plugins.c (nonexistent) +++ tags/1.2.3/src/plugins.c (revision 8969) @@ -0,0 +1,110 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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; +} + +/* ---------------------------------------------------------------- */ +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.3/src/plugins.h =================================================================== --- tags/1.2.3/src/plugins.h (nonexistent) +++ tags/1.2.3/src/plugins.h (revision 8969) @@ -0,0 +1,89 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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); + +/* 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.3/src/polyarea.h =================================================================== --- tags/1.2.3/src/polyarea.h (nonexistent) +++ tags/1.2.3/src/polyarea.h (revision 8969) @@ -0,0 +1,171 @@ +/* + 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., 675 Mass Ave, Cambridge, MA 02139, 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 + +#ifndef min +#define min(x, y) ((x) < (y) ? (x) : (y)) +#endif + +#ifndef max +#define max(x, y) ((x) > (y) ? (x) : (y)) +#endif + + +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_exclide(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); + +#endif /* PCB_POLYAREA_H */ Index: tags/1.2.3/src/polygon.c =================================================================== --- tags/1.2.3/src/polygon.c (nonexistent) +++ tags/1.2.3/src/polygon.c (revision 8969) @@ -0,0 +1,1880 @@ +/* + * 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 + * + */ + + +/* + +Here's a brief tour of the data and life of a polygon, courtesy of Ben +Jackson: + +A PCB pcb_polygon_t contains an array of points outlining the polygon. +This is what is manipulated by the UI and stored in the saved PCB. + +A pcb_polygon_t also contains a pcb_polyarea_t called 'Clipped' which is +computed dynamically by InitClip every time a board is loaded. The +point array is converted to a pcb_polyarea_t by original_poly and then holes +are cut in it by clearPoly. After that it is maintained dynamically +as parts are added, moved or removed (this is why sometimes bugs can +be fixed by just re-loading the board). + +A pcb_polyarea_t consists of a linked list of pcb_pline_t structures. The head of +that list is pcb_polyarea_t.contours. The first contour is an outline of a +filled region. All of the subsequent pcb_pline_ts are holes cut out of that +first contour. pcb_polyarea_ts are in a doubly-linked list and each member +of the list is an independent (non-overlapping) area with its own +outline and holes. The function biggest() finds the largest pcb_polyarea_t +so that pcb_polygon_t.Clipped points to that shape. The rest of the +polygon still exists, it's just ignored when turning the polygon into +copper. + +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). + +*/ + +/* special polygon editing routines + */ + +#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 "obj_pinvia_therm.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_LINE_BATCH_SIZE 20 + +static double rotate_circle_seg[4]; + +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_polygon_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_polygon_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_polygon_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_polygon_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_polygon_t *poly = (pcb_polygon_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_polygon_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; +} + +static pcb_polyarea_t *original_poly(pcb_polygon_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_polygon_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 */ +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) +{ + pcb_pline_t *contour = NULL; + pcb_polyarea_t *np = NULL; + pcb_vector_t v; + pcb_box_t ends; + int i, segs; + double ang, da, rx, ry; + long half; + double radius_adj; + + 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 */ + 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; + } + /* now add other round cap */ + ang = a->StartAngle; + v[0] = a->X - rx * cos(ang * PCB_M180) * (1 - radius_adj); + v[1] = a->Y + ry * sin(ang * PCB_M180) * (1 - radius_adj); + pcb_poly_frac_circle(contour, ends.X1, ends.Y1, v, 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_polyarea_t *tmp1, *tmp2, *res; + + delta = (a->Delta < 0) ? -a->Delta : a->Delta; + + /* 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) { + 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); + tmp2 = ArcPolyNoIntersect(&seg2, thick); + pcb_polyarea_boolean_free(tmp1, tmp2, &res, PCB_PBO_UNITE); + return res; + } + + return ArcPolyNoIntersect(a, thick); +} + +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 */ +static int Subtract(pcb_polyarea_t * np1, pcb_polygon_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; +} + +/* 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)) { + 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 = ThermPoly(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_polygon_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, d->pcb, pin); + + if (PCB_FLAG_THERM_TEST(i, pin)) { + if (!np) + return 0; + } + else { + if (!np) + return -1; + } + + return Subtract(np, p, pcb_true); +} + +static int SubtractLine(pcb_line_t * line, pcb_polygon_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, line)) + return 0; + if (!(np = pcb_poly_from_line(line, line->Thickness + line->Clearance))) + return -1; + return Subtract(np, p, pcb_true); +} + +static int SubtractArc(pcb_arc_t * arc, pcb_polygon_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, 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_polygon_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_polygon_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_polygon_t *polygon; + pcb_bool solder; + pcb_polyarea_t *accumulate; + int batch_size; + jmp_buf env; +}; + +static void subtract_accumulated(struct cpInfo *info, pcb_polygon_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_polygon_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 = ThermPoly((pcb_board_t *) (info->data->pcb), 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 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_polygon_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, 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; +} + +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_polygon_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_polygon_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_FLAG_TEST(PCB_FLAG_CLEARLINE, line)) + return PCB_R_DIR_NOT_FOUND; + polygon = info->polygon; + + if (!(np = pcb_poly_from_line(line, line->Thickness + line->Clearance))) + 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_polygon_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_polygon_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; + + if (!(pcb_layer_flags(PCB, pcb_layer_id(Data, Layer)) & PCB_LYT_COPPER)) { + 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_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; + subtract_accumulated(&info, polygon); + } + polygon->NoHolesValid = 0; + return r; +} + +static int Unsubtract(pcb_polyarea_t * np1, pcb_polygon_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_polygon_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 UnsubtractArc(pcb_arc_t * arc, pcb_layer_t * l, pcb_polygon_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, 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_polygon_t * p) +{ + pcb_polyarea_t *np; + + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, 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_polygon_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_polygon_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_polygon_t * p) +{ + if (inhibit) + return 0; + if (p->Clipped) + pcb_polyarea_free(&p->Clipped); + p->Clipped = original_poly(p); + pcb_poly_contours_free(&p->NoHoles); + if (!p->Clipped) + return 0; + assert(pcb_poly_valid(p->Clipped)); + 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_polygon_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_POLYGON_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_polygon_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 + */ +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; + } + } +} + +/* --------------------------------------------------------------------------- + * 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_polygon_t *dst, pcb_polygon_t *src) +{ + pcb_polygon_t p; + memcpy(dst, src, ((char *)&p.link - (char *)&p)); +} + +/* --------------------------------------------------------------------------- + * moves the data of the attached (new) polygon to the current layer + */ +void pcb_polygon_copy_attached_to_layer(void) +{ + pcb_polygon_t *polygon; + int saveID; + + /* move data to layer and clear attached struct */ + polygon = pcb_poly_new(CURRENT, pcb_no_flags()); + saveID = polygon->ID; + poly_copy_data(polygon, &pcb_crosshair.AttachedPolygon); + polygon->ID = saveID; + PCB_FLAG_SET(PCB_FLAG_CLEARPOLY, polygon); + if (conf_core.editor.full_poly) + PCB_FLAG_SET(PCB_FLAG_FULLPOLY, polygon); + memset(&pcb_crosshair.AttachedPolygon, 0, sizeof(pcb_polygon_t)); + + pcb_add_polygon_on_layer(CURRENT, polygon); + + pcb_poly_init_clip(PCB->Data, CURRENT, polygon); + DrawPolygon(CURRENT, 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_POLYGON, CURRENT, polygon, polygon); + pcb_undo_inc_serial(); +} + +/* 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_polygon_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_polygon_t *, int, void *, void *); +}; + +static pcb_r_dir_t subtract_plow(pcb_data_t *Data, pcb_layer_t *Layer, pcb_polygon_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_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_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_polygon_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_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_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; +} + +static pcb_r_dir_t plow_callback(const pcb_box_t * b, void *cl) +{ + struct plow_info *plow = (struct plow_info *) cl; + pcb_polygon_t *polygon = (pcb_polygon_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_polygon_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 (type == PCB_TYPE_PIN || ptr1 == ptr2 || ptr1 == NULL) { + LAYER_LOOP(Data, pcb_max_layer); + { + if (!(pcb_layer_flags(PCB, pcb_layer_id(Data, 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_LINE: + case PCB_TYPE_ARC: + case PCB_TYPE_TEXT: + /* the cast works equally well for lines and arcs */ + if (!PCB_FLAG_TEST(PCB_FLAG_CLEARLINE, (pcb_line_t *) ptr2)) + return 0; + /* non-copper (e.g. silk, outline) doesn't plow */ + if (!(pcb_layer_flags(PCB, pcb_layer_id(Data, (pcb_layer_t *) ptr1) & PCB_LYT_COPPER))) + return 0; + 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) +{ + if (type == PCB_TYPE_POLYGON) + pcb_poly_init_clip(PCB->Data, (pcb_layer_t *) ptr1, (pcb_polygon_t *) ptr2); + else + pcb_poly_plows(Data, type, ptr1, ptr2, add_plow); +} + +void pcb_poly_clear_from_poly(pcb_data_t * Data, int type, void *ptr1, void *ptr2) +{ + if (type == PCB_TYPE_POLYGON) + pcb_poly_init_clip(PCB->Data, (pcb_layer_t *) ptr1, (pcb_polygon_t *) ptr2); + else + pcb_poly_plows(Data, type, ptr1, ptr2, subtract_plow); +} + +pcb_bool pcb_poly_isects_poly(pcb_polyarea_t * a, pcb_polygon_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_polygon_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_polygon_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_polygon_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_polygon_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_polygon_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_polygon_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; + ErasePolygon(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_polygon_t *newone; + + if (p->contours->area > PCB->IsleArea) { + newone = pcb_poly_new(layer, 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_POLYGON, 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); + DrawPolygon(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_polygon_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_polygon_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, 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); + + DrawPolygon(Layer, Polygon); + /* add to undo list */ + pcb_undo_add_obj_to_create(PCB_TYPE_POLYGON, Layer, Polygon, Polygon); + } + while ((pa = pa->f) != Input); + + pcb_board_set_changed_flag(pcb_true); +} Index: tags/1.2.3/src/polygon.h =================================================================== --- tags/1.2.3/src/polygon.h (nonexistent) +++ tags/1.2.3/src/polygon.h (revision 8969) @@ -0,0 +1,96 @@ +/* + * 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 + * + */ + +/* prototypes for polygon editing routines */ + +#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_polygon_t *polygon, pcb_point_t *point); +pcb_cardinal_t pcb_poly_contour_point(pcb_polygon_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_contour_prev_point(pcb_polygon_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_contour_next_point(pcb_polygon_t *polygon, pcb_cardinal_t point); +pcb_cardinal_t pcb_poly_get_lowest_distance_point(pcb_polygon_t *, pcb_coord_t, pcb_coord_t); +pcb_bool pcb_poly_remove_excess_points(pcb_layer_t *, pcb_polygon_t *); +void pcb_polygon_go_to_prev_point(void); +void pcb_polygon_close_poly(void); +void pcb_polygon_copy_attached_to_layer(void); +int pcb_poly_holes(pcb_polygon_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_polygon_t *, int, void *, void *)); +void pcb_poly_compute_no_holes(pcb_polygon_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_polygon_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); + +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_polygon_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_polygon_t *); +pcb_bool pcb_poly_is_point_in_p_ignore_holes(pcb_coord_t, pcb_coord_t, pcb_polygon_t *); +pcb_bool pcb_poly_is_rect_in_p(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_polygon_t *); +pcb_bool pcb_poly_isects_poly(pcb_polyarea_t *, pcb_polygon_t *, pcb_bool); +pcb_bool pcb_poly_morph(pcb_layer_t *, pcb_polygon_t *); +void pcb_poly_no_holes_dicer(pcb_polygon_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); + + +#endif Index: tags/1.2.3/src/polygon1.c =================================================================== --- tags/1.2.3/src/polygon1.c (nonexistent) +++ tags/1.2.3/src/polygon1.c (revision 8969) @@ -0,0 +1,3215 @@ +/* + 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., 675 Mass Ave, Cambridge, MA 02139, 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" + + +#define ROUND(a) (long)((a) > 0 ? ((a) + 0.5) : ((a) - 0.5)) + +#define EPSILON (1E-8) +#define IsZero(a, b) (fabs((a) - (b)) < EPSILON) + +/*********************************************************************/ +/* 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 = 0x7fffffff; + c->xmax = c->ymax = 0x80000000; + 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 = 0x7fffffff; + 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 pints */ +/* 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 */ + +/* 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.3/src/polygon_act.c =================================================================== --- tags/1.2.3/src/polygon_act.c (nonexistent) +++ tags/1.2.3/src/polygon_act.c (revision 8969) @@ -0,0 +1,148 @@ +/* + * 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_POLYGON, &ptr1, &ptr2, &ptr3)) != PCB_TYPE_NONE) { + pcb_poly_morph((pcb_layer_t *) ptr1, (pcb_polygon_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|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 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) { + 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; + + /* 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.3/src/rats.c =================================================================== --- tags/1.2.3/src/rats.c (nonexistent) +++ tags/1.2.3/src/rats.c (revision 8969) @@ -0,0 +1,943 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "vtptr.h" +#include "obj_rat_draw.h" + +#define STEP_POINT 100 + +#define TRIEDFIRST 0x1 +#define BESTFOUND 0x2 + +/* --------------------------------------------------------------------------- + * some forward declarations + */ +static pcb_bool FindPad(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 *); + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +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 pad from an element name and pin number + */ +static pcb_bool FindPad(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; + + 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->type = PCB_TYPE_PAD; + conn->ptr1 = element; + conn->ptr2 = 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->type = PCB_TYPE_PIN; + conn->ptr1 = element; + conn->ptr2 = pin; + conn->group = Sgrp; /* any layer will do */ + conn->X = pin->X; + conn->Y = pin->Y; + return pcb_true; + } + } + + return pcb_false; +} + +/*-------------------------------------------------------------------------- + * parse 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) +{ + 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 (FindPad(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); +} + +/* --------------------------------------------------------------------------- + * Read the library-netlist build a pcb_true Netlist structure + */ + +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) { + PCB_PIN_ALL_LOOP(PCB->Data); + { + pin->Spare = NULL; + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pin); + } + PCB_ENDALL_LOOP; + PCB_PAD_ALL_LOOP(PCB->Data); + { + pad->Spare = NULL; + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pad); + } + PCB_ENDALL_LOOP; + 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, 0, 0, 0, 0, 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.ptr2)) + pcb_message(PCB_MSG_ERROR, _ + ("Error! Element %s pin %s appears multiple times in the netlist file.\n"), + PCB_ELEM_NAME_REFDES((pcb_element_t *) LastPoint.ptr1), + (LastPoint.type == + PCB_TYPE_PIN) ? ((pcb_pin_t *) LastPoint.ptr2)->Number : ((pcb_pad_t *) LastPoint.ptr2)->Number); + 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.ptr2); + if (LastPoint.type == PCB_TYPE_PIN) + ((pcb_pin_t *) LastPoint.ptr2)->Spare = (void *) menu; + else + ((pcb_pad_t *) LastPoint.ptr2)->Spare = (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.ptr2); + if (LastPoint.type == PCB_TYPE_PIN) + ((pcb_pin_t *) LastPoint.ptr2)->Spare = (void *) menu; + else + ((pcb_pad_t *) LastPoint.ptr2)->Spare = (void *) menu; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + } + /* clear all visit marks */ + PCB_PIN_ALL_LOOP(PCB->Data); + { + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pin); + } + PCB_ENDALL_LOOP; + PCB_PAD_ALL_LOOP(PCB->Data); + { + PCB_FLAG_CLEAR(PCB_FLAG_DRC, pad); + } + PCB_ENDALL_LOOP; + 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 pcb_bool CheckShorts(pcb_lib_menu_t *theNet) +{ + pcb_bool newone, warn = pcb_false; + int i; + vtptr_t generic; + /* the first connection was starting point so + * the menu is always non-null + */ + void **menu; + + vtptr_init(&generic); + menu = vtptr_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))) { + warn = pcb_true; + if (!pin->Spare) { + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to %s pin %s\n"), + &theNet->Name[2], PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), PCB_UNKNOWN(pin->Number)); + pcb_stub_rat_found_short(pin, NULL, &theNet->Name[2]); + continue; + } + newone = pcb_true; + for(i = 0; i < vtptr_len(&generic); i++) { + if (generic.array[i] == pin->Spare) { + newone = pcb_false; + break; + } + } + + if (newone) { + menu = vtptr_alloc_append(&generic, 1); + *menu = pin->Spare; + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to net \"%s\"\n"), + &theNet->Name[2], &((pcb_lib_menu_t *) (pin->Spare))->Name[2]); + pcb_stub_rat_found_short(pin, NULL, &theNet->Name[2]); + } + } + } + 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; + if (!pad->Spare) { + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to %s pad %s\n"), + &theNet->Name[2], PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), PCB_UNKNOWN(pad->Number)); + pcb_stub_rat_found_short(NULL, pad, &theNet->Name[2]); + continue; + } + newone = pcb_true; + for(i = 0; i < vtptr_len(&generic); i++) { + if (generic.array[i] == pad->Spare) { + newone = pcb_false; + break; + } + } + + if (newone) { + menu = vtptr_alloc_append(&generic, 1); + *menu = pad->Spare; + pcb_message(PCB_MSG_WARNING, _("Warning! Net \"%s\" is shorted to net \"%s\"\n"), + &theNet->Name[2], &((pcb_lib_menu_t *) (pad->Spare))->Name[2]); + pcb_stub_rat_found_short(NULL, pad, &theNet->Name[2]); + } + } + } + PCB_ENDALL_LOOP; + vtptr_uninit(&generic); + return (warn); +} + + +/* --------------------------------------------------------------------------- + * 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_connection_t *conn; + pcb_cardinal_t m, n; + pcb_bool Warned = pcb_false; + + 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].type, a->Connection[0].ptr1, a->Connection[0].ptr2, a->Connection[0].ptr2, 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].ptr2); + 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].ptr2)) { + PCB_FLAG_CLEAR(PCB_FLAG_DRC, (pcb_pin_t *) b->Connection[0].ptr2); + TransferNet(Netl, b, a); + /* back up since new subnet is now at old index */ + n--; + } + } + /* 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_ALL_LOOP(PCB->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->type = PCB_TYPE_LINE; + conn->ptr1 = layer; + conn->ptr2 = 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->type = PCB_TYPE_LINE; + conn->ptr1 = layer; + conn->ptr2 = line; + conn->group = pcb_layer_get_group_(layer); + conn->menu = NULL; + } + } + PCB_ENDALL_LOOP; + /* add polygons so the auto-router can see them as targets */ + PCB_POLY_ALL_LOOP(PCB->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->type = PCB_TYPE_POLYGON; + conn->ptr1 = layer; + conn->ptr2 = polygon; + conn->group = pcb_layer_get_group_(layer); + conn->menu = NULL; /* agnostic view of where it belongs */ + } + } + PCB_ENDALL_LOOP; + PCB_VIA_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_DRC, via)) { + conn = pcb_rat_connection_alloc(a); + conn->X = via->X; + conn->Y = via->Y; + conn->type = PCB_TYPE_VIA; + conn->ptr1 = via; + conn->ptr2 = via; + conn->group = Sgrp; + } + } + PCB_END_LOOP; + 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_polygon_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->type == PCB_TYPE_POLYGON && + (polygon = (pcb_polygon_t *) conn1->ptr2) && + !(distance == 0 && + firstpoint && firstpoint->type == PCB_TYPE_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->type == PCB_TYPE_POLYGON && + (polygon = (pcb_polygon_t *) conn2->ptr2) && + !(distance == 0 && + firstpoint && firstpoint->type == PCB_TYPE_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); + DrawRat(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); +} + + +/* --------------------------------------------------------------------------- + * AddAllRats puts 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 *)) +{ + 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->ptr2)) { + 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_WARNING, "%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_WARNING, _("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->ptr2)) { + 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; +} + + /* These next two functions moved from the original netlist.c as part of the + | gui code separation for the Gtk port. + */ +pcb_rat_t *pcb_rat_add_net(void) +{ + static int ratDrawn = 0; + char name1[256], *name2; + pcb_cardinal_t group1, group2; + char ratname[20]; + 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, &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); + } + if (PCB_ELEM_NAME_REFDES((pcb_element_t *) ptr1) == NULL || *PCB_ELEM_NAME_REFDES((pcb_element_t *) ptr1) == 0) { + 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(found, ptr1, 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); + } + if (PCB_ELEM_NAME_REFDES((pcb_element_t *) ptr1) == NULL || *PCB_ELEM_NAME_REFDES((pcb_element_t *) ptr1) == 0) { + 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(found, ptr1, 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(int type, void *ptr1, void *ptr2) +{ + static char name[256]; + char *num; + + switch (type) { + case PCB_TYPE_PIN: + num = ((pcb_pin_t *) ptr2)->Number; + break; + case PCB_TYPE_PAD: + num = ((pcb_pad_t *) ptr2)->Number; + break; + default: + return (NULL); + } + strcpy(name, PCB_UNKNOWN(PCB_ELEM_NAME_REFDES((pcb_element_t *) ptr1))); + 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.3/src/rats.h =================================================================== --- tags/1.2.3/src/rats.h (nonexistent) +++ tags/1.2.3/src/rats.h (revision 8969) @@ -0,0 +1,75 @@ +/* + * 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., 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 + * + */ + +/* prototypes for rats routines */ + +#ifndef PCB_RATS_H +#define PCB_RATS_H + +#include "config.h" +#include "netlist.h" +#include "layer.h" +#include "layer_grp.h" + +/* --------------------------------------------------------------------------- + * structure used by device drivers + */ + + +struct pcb_connection_s { /* holds a connection (rat) */ + pcb_coord_t X, Y; /* coordinate of connection */ + long int type; /* type of object in ptr1 - 3 */ + void *ptr1, *ptr2; /* 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); +char *pcb_connection_name(int, void *, void *); + +pcb_bool pcb_rat_add_all(pcb_bool, void (*)(register pcb_connection_t *, register pcb_connection_t *, register pcb_route_style_t *)); +pcb_bool pcb_rat_seek_pad(pcb_lib_entry_t *, pcb_connection_t *, pcb_bool); + +pcb_netlist_t *pcb_rat_proc_netlist(pcb_lib_t *); +pcb_netlist_list_t pcb_rat_collect_subnets(pcb_bool); +pcb_connection_t *pcb_rat_connection_alloc(pcb_net_t *); + +#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.3/src/rats_act.c =================================================================== --- tags/1.2.3/src/rats_act.c (nonexistent) +++ tags/1.2.3/src/rats_act.c (revision 8969) @@ -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(PCB_TYPE_RATLINE, shorty, shorty, shorty); + PCB_FLAG_SET(PCB_FLAG_SELECTED, shorty); + DrawRat(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.3/src/rats_patch.c =================================================================== --- tags/1.2.3/src/rats_patch.c (nonexistent) +++ tags/1.2.3/src/rats_patch.c (revision 8969) @@ -0,0 +1,498 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2015 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +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 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 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 = 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.3/src/rats_patch.h =================================================================== --- tags/1.2.3/src/rats_patch.h (nonexistent) +++ tags/1.2.3/src/rats_patch.h (revision 8969) @@ -0,0 +1,97 @@ +/* + * COPYRIGHT + * + * pcb-rnd, interactive printed circuit board design + * Copyright (C) 2013..2015 Tibor 'Igor2' Palinkas + * + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 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.3/src/remove.c =================================================================== --- tags/1.2.3/src/remove.c (nonexistent) +++ tags/1.2.3/src/remove.c (revision 8969) @@ -0,0 +1,124 @@ +/* + * 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 + * + */ + +/* 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" + +/* --------------------------------------------------------------------------- + * some local types + */ +static pcb_opfunc_t RemoveFunctions = { + RemoveLine_op, + RemoveText_op, + RemovePolygon_op, + RemoveVia, + RemoveElement_op, + NULL, + NULL, + NULL, + RemoveLinePoint, + RemovePolygonPoint, + RemoveArc_op, + RemoveRat, + RemoveArcPoint_op, +}; + +static pcb_opfunc_t DestroyFunctions = { + DestroyLine, + DestroyText, + DestroyPolygon, + DestroyVia, + DestroyElement, + NULL, + NULL, + NULL, + NULL, + DestroyPolygonPoint, + DestroyArc, + DestroyRat, + NULL +}; + +/* ---------------------------------------------------------------------- + * 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, &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); +} + +/* --------------------------------------------------------------------------- + * remove object as referred by pointers and type + * allocated memory is destroyed assumed to already be erased + */ +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.3/src/remove.h =================================================================== --- tags/1.2.3/src/remove.h (nonexistent) +++ tags/1.2.3/src/remove.h (revision 8969) @@ -0,0 +1,45 @@ +/* + * 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 + * + */ + +/* prototypes for remove routines */ + +#ifndef PCB_REMOVE_H +#define PCB_REMOVE_H + +#include "config.h" + +/* --------------------------------------------------------------------------- + * some constants + */ +#define PCB_REMOVE_TYPES \ + (PCB_TYPE_VIA | PCB_TYPE_LINE_POINT | PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT | \ + PCB_TYPE_POLYGON_POINT | PCB_TYPE_POLYGON | PCB_TYPE_RATLINE | PCB_TYPE_ARC | PCB_TYPE_ARC_POINT) + +pcb_bool pcb_remove_selected(void); +void *pcb_remove_object(int, void *, void *, void *); +void *pcb_destroy_object(pcb_data_t *, int, void *, void *, void *); + +#endif Index: tags/1.2.3/src/remove_act.c =================================================================== --- tags/1.2.3/src/remove_act.c (nonexistent) +++ tags/1.2.3/src/remove_act.c (revision 8969) @@ -0,0 +1,108 @@ +/* + * 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 "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); + + Note.X = pcb_crosshair.X; + Note.Y = pcb_crosshair.Y; + + if (id == -1) { /* no arg */ + if (pcb_remove_selected() == pcb_false) + id = F_Object; + } + + switch (id) { + case F_Object: + 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.3/src/rotate.c =================================================================== --- tags/1.2.3/src/rotate.c (nonexistent) +++ tags/1.2.3/src/rotate.c (revision 8969) @@ -0,0 +1,124 @@ +/* + * 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 + * + */ + + +/* 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_line_draw.h" +#include "obj_rat_draw.h" + +/* ---------------------------------------------------------------------- + * some local identifiers + */ +static pcb_opfunc_t Rotate90Functions = { + Rotate90Line, + Rotate90Text, + NULL, + NULL, + Rotate90Element, + Rotate90ElementName, + NULL, + NULL, + Rotate90LinePoint, + NULL, + Rotate90Arc, + NULL, + NULL +}; + +/* --------------------------------------------------------------------------- + * 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); +} + +/* ---------------------------------------------------------------------- + * rotates an objects at the cursor position as identified by its ID + * the center of rotation is determined by the current cursor location + */ +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); + + pcb_undo_add_obj_to_rotate(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_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, &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); + } +} Index: tags/1.2.3/src/rotate.h =================================================================== --- tags/1.2.3/src/rotate.h (nonexistent) +++ tags/1.2.3/src/rotate.h (revision 8969) @@ -0,0 +1,74 @@ +/* + * 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 + * + */ + +/* prototypes for transform routines */ + +#ifndef PCB_ROTATE_H +#define PCB_ROTATE_H + +#include "config.h" +#include "global_typedefs.h" + +/* --------------------------------------------------------------------------- + * some useful transformation macros and constants + */ +#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_ELEMENT | PCB_TYPE_TEXT | PCB_TYPE_ELEMENT_NAME | PCB_TYPE_ARC | PCB_TYPE_LINE_POINT | PCB_TYPE_LINE) + +void *pcb_obj_rotate90(int, void *, void *, void *, pcb_coord_t, pcb_coord_t, unsigned); +void pcb_screen_obj_rotate90(pcb_coord_t, pcb_coord_t, unsigned); +void pcb_point_rotate90(pcb_point_t *Point, pcb_coord_t X, pcb_coord_t Y, unsigned Number); + +static inline PCB_FUNC_UNUSED 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.3/src/route.c =================================================================== --- tags/1.2.3/src/route.c (nonexistent) +++ tags/1.2.3/src/route.c (revision 8969) @@ -0,0 +1,675 @@ +/* + * 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" + + +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_get_layer(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 */ + EraseLine(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); + DrawLine(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); + DrawLine(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); + DrawArc(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 a line + *---------------------------------------------------------*/ +void +pcb_route_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 thickness ) +{ + pcb_coord_t dx = x2 - x1; + pcb_coord_t dy = y2 - y1; + double h = (dx != 0 || dy != 0) ? (0.5 * thickness / sqrt(PCB_SQUARE(dx) + PCB_SQUARE(dy))) : 0.0; + pcb_coord_t ox = dy * h + 0.5 * SGN(dy); + pcb_coord_t oy = -(dx * h + 0.5 * SGN(dx)); + + pcb_gui->draw_line(GC, x1 + ox, y1 + oy, x2 + ox, y2 + oy); + + if (coord_abs(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, thickness / 2, thickness / 2, angle - 180, 180); + pcb_gui->draw_arc(GC, x2, y2, thickness / 2, thickness / 2, angle, 180); + } +} + +/*----------------------------------------------------------- + * 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(p_obj->layer); + if(layer) + pcb_gui->set_color(GC,layer->Color); + + switch(p_obj->type) { + case PCB_TYPE_LINE : + pcb_route_draw_line(GC,p_obj->point1.X,p_obj->point1.Y,p_obj->point2.X,p_obj->point2.Y,p_route->thickness); + 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_route_draw_line(GC,p_obj->point1.X,p_obj->point1.Y,p_obj->point2.X,p_obj->point2.Y,thickness); + 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.3/src/route.h =================================================================== --- tags/1.2.3/src/route.h (nonexistent) +++ tags/1.2.3/src/route.h (revision 8969) @@ -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.3/src/route_style.c =================================================================== --- tags/1.2.3/src/route_style.c (nonexistent) +++ tags/1.2.3/src/route_style.c (revision 8969) @@ -0,0 +1,236 @@ +/* + * 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., 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 + * + */ +#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; + +/*! \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) != 0) && (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 + + +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.3/src/route_style.h =================================================================== --- tags/1.2.3/src/route_style.h (nonexistent) +++ tags/1.2.3/src/route_style.h (revision 8969) @@ -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-0 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.3/src/rtree.c =================================================================== --- tags/1.2.3/src/rtree.c (nonexistent) +++ tags/1.2.3/src/rtree.c (revision 8969) @@ -0,0 +1,1005 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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! + */ + +/* the number of entries in each rtree node + * 4 - 7 seem to be pretty good settings + */ +#define M_SIZE 6 + +/* 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; +} Index: tags/1.2.3/src/rtree.h =================================================================== --- tags/1.2.3/src/rtree.h (nonexistent) +++ tags/1.2.3/src/rtree.h (revision 8969) @@ -0,0 +1,85 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 */ +}; + +/* 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); + +#endif Index: tags/1.2.3/src/search.c =================================================================== --- tags/1.2.3/src/search.c (nonexistent) +++ tags/1.2.3/src/search.c (revision 8969) @@ -0,0 +1,1477 @@ +/* + * 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 + * + */ + + +/* 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" + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +static double PosX, PosY; /* search position for subroutines */ +static pcb_coord_t SearchRadius; +static pcb_box_t SearchBox; +static pcb_layer_t *SearchLayer; + +/* --------------------------------------------------------------------------- + * some local prototypes. The first parameter includes PCB_TYPE_LOCKED if we + * want to include locked types in the search. + */ +static pcb_bool SearchLineByLocation(int, pcb_layer_t **, pcb_line_t **, pcb_line_t **); +static pcb_bool SearchArcByLocation(int, pcb_layer_t **, pcb_arc_t **, pcb_arc_t **); +static pcb_bool SearchRatLineByLocation(int, pcb_rat_t **, pcb_rat_t **, pcb_rat_t **); +static pcb_bool SearchTextByLocation(int, pcb_layer_t **, pcb_text_t **, pcb_text_t **); +static pcb_bool SearchPolygonByLocation(int, pcb_layer_t **, pcb_polygon_t **, pcb_polygon_t **); +static pcb_bool SearchPinByLocation(int, pcb_element_t **, pcb_pin_t **, pcb_pin_t **); +static pcb_bool SearchPadByLocation(int, pcb_element_t **, pcb_pad_t **, pcb_pad_t **, pcb_bool); +static pcb_bool SearchViaByLocation(int, pcb_pin_t **, pcb_pin_t **, pcb_pin_t **); +static pcb_bool SearchElementNameByLocation(int, pcb_element_t **, pcb_text_t **, pcb_text_t **, pcb_bool); +static pcb_bool SearchLinePointByLocation(int, pcb_layer_t **, pcb_line_t **, pcb_point_t **); +static pcb_bool SearchArcPointByLocation(int, pcb_layer_t **, pcb_arc_t **, int **); +static pcb_bool SearchPointByLocation(int, pcb_layer_t **, pcb_polygon_t **, pcb_point_t **); +static pcb_bool SearchElementByLocation(int, pcb_element_t **, pcb_element_t **, pcb_element_t **, pcb_bool); + +/* --------------------------------------------------------------------------- + * searches a via + */ +struct ans_info { + void **ptr1, **ptr2, **ptr3; + pcb_bool BackToo; + double area; + int locked; /* This will be zero or PCB_FLAG_LOCK */ +}; + +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; + + if (PCB_FLAG_TEST(i->locked, ptr1)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + 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 pin + * starts with the newest element + */ +static pcb_bool SearchPinByLocation(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + 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; + + if (PCB_FLAG_TEST(i->locked, ptr1)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + 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; + int locked; +}; + +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; + + if (PCB_FLAG_TEST(i->locked, l)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + *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; + + if (PCB_FLAG_TEST(i->locked, line)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + 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; + int locked; + 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; + + if (PCB_FLAG_TEST(i->locked, a)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, pcb_layer_t ** Layer, pcb_arc_t ** Arc, pcb_arc_t ** Dummy) +{ + struct arc_info info; + + info.Arc = Arc; + info.Dummy = Dummy; + info.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + *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; + + if (PCB_FLAG_TEST(i->locked, text)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + 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_polygon_t *polygon = (pcb_polygon_t *) box; + struct ans_info *i = (struct ans_info *) cl; + + if (PCB_FLAG_TEST(i->locked, polygon)) + return PCB_R_DIR_NOT_FOUND; + + 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(int locked, pcb_layer_t ** Layer, pcb_polygon_t ** Polygon, pcb_polygon_t ** Dummy) +{ + struct ans_info info; + + *Layer = SearchLayer; + info.ptr2 = (void **) Polygon; + info.ptr3 = (void **) Dummy; + info.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + + 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; + + if (PCB_FLAG_TEST(i->locked, line)) + return PCB_R_DIR_NOT_FOUND; + + /* 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; + + + if (PCB_FLAG_TEST(i->locked, arc)) + return PCB_R_DIR_NOT_FOUND; + + /* 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + 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(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + 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 + */ +static pcb_bool SearchPointByLocation(int locked, pcb_layer_t ** Layer, pcb_polygon_t ** Polygon, pcb_point_t ** Point) +{ + double d, least; + pcb_bool found = pcb_false; + + least = SearchRadius + PCB_MAX_POLYGON_POINT_DISTANCE; + *Layer = SearchLayer; + PCB_POLY_LOOP(*Layer); + { + PCB_POLY_POINT_LOOP(polygon); + { + d = pcb_distance(point->X, point->Y, PosX, PosY); + if (d < least) { + least = d; + *Polygon = polygon; + *Point = point; + found = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + if (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; + + if (PCB_FLAG_TEST(i->locked, text)) + return PCB_R_DIR_NOT_FOUND; + + 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 + * the search starts with the last element and goes back to the beginning + */ +static pcb_bool +SearchElementNameByLocation(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + 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; + + if (PCB_FLAG_TEST(i->locked, element)) + return PCB_R_DIR_NOT_FOUND; + + 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 + * the search starts with the last element and goes back to the beginning + * if more than one element matches, the smallest one is taken + */ +static pcb_bool +SearchElementByLocation(int locked, 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.locked = (locked & PCB_TYPE_LOCKED) ? 0 : PCB_FLAG_LOCK; + if (pcb_r_search(PCB->Data->element_tree, &SearchBox, NULL, element_callback, &info, NULL)) + return pcb_true; + } + return pcb_false; +} + +/* --------------------------------------------------------------------------- + * checks if a point is on a pin + */ +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; +} + +/* --------------------------------------------------------------------------- + * checks 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. + */ +pcb_bool pcb_is_point_on_line(pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius, pcb_line_t *Line) +{ + double D1, D2, L; + + /* Get length of segment */ + L = pcb_distance(Line->Point1.X, Line->Point1.Y, Line->Point2.X, Line->Point2.Y); + if (L < 0.1) + return pcb_distance(X, Y, Line->Point1.X, Line->Point1.Y) < Radius + Line->Thickness / 2; + + /* 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 sqrt(D1 * D1 + D2 * D2) <= Radius + Line->Thickness / 2; +} + +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 + */ +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); +} + +static int /*checks if a point (of null radius) is in a slanted rectangle */ 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: 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 square + */ +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; + + /* 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. + */ +int pcb_search_obj_by_location(unsigned Type, void **Result1, void **Result2, void **Result3, pcb_coord_t X, pcb_coord_t Y, pcb_coord_t Radius) +{ + void *r1, *r2, *r3; + void **pr1 = &r1, **pr2 = &r2, **pr3 = &r3; + int i; + double HigherBound = 0; + int HigherAvail = PCB_TYPE_NONE; + int locked = Type & PCB_TYPE_LOCKED; + /* 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_POLYGON; + } + + if (Type & PCB_TYPE_RATLINE && PCB->RatOn && + SearchRatLineByLocation(locked, (pcb_rat_t **) Result1, (pcb_rat_t **) Result2, (pcb_rat_t **) Result3)) + return (PCB_TYPE_RATLINE); + + if (Type & PCB_TYPE_VIA && SearchViaByLocation(locked, (pcb_pin_t **) Result1, (pcb_pin_t **) Result2, (pcb_pin_t **) Result3)) + return (PCB_TYPE_VIA); + + if (Type & PCB_TYPE_PIN && SearchPinByLocation(locked, (pcb_element_t **) pr1, (pcb_pin_t **) pr2, (pcb_pin_t **) pr3)) + HigherAvail = PCB_TYPE_PIN; + + if (!HigherAvail && Type & PCB_TYPE_PAD && + SearchPadByLocation(locked, (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(locked, (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(locked, (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; + } + + 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->On) { + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && + Type & PCB_TYPE_POLYGON_POINT && + SearchPointByLocation(locked, (pcb_layer_t **) Result1, (pcb_polygon_t **) Result2, (pcb_point_t **) Result3)) + return (PCB_TYPE_POLYGON_POINT); + + if ((HigherAvail & (PCB_TYPE_PIN | PCB_TYPE_PAD)) == 0 && + Type & PCB_TYPE_LINE_POINT && + SearchLinePointByLocation(locked, (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(locked, (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(locked, (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(locked, (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(locked, (pcb_layer_t **) Result1, (pcb_text_t **) Result2, (pcb_text_t **) Result3)) + return (PCB_TYPE_TEXT); + + if (Type & PCB_TYPE_POLYGON && + SearchPolygonByLocation(locked, (pcb_layer_t **) Result1, (pcb_polygon_t **) Result2, (pcb_polygon_t **) Result3)) { + if (HigherAvail) { + pcb_box_t *box = &(*(pcb_polygon_t **) Result2)->BoundingBox; + double area = (double) (box->X2 - box->X1) * (double) (box->X2 - box->X1); + if (HigherBound < area) + break; + else + return (PCB_TYPE_POLYGON); + } + else + return (PCB_TYPE_POLYGON); + } + } + } + /* 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); + } + + /* search the 'invisible objects' last */ + if (!PCB->InvisibleObjectsOn) + return (PCB_TYPE_NONE); + + if (Type & PCB_TYPE_PAD && + SearchPadByLocation(locked, (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(locked, (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(locked, (pcb_element_t **) Result1, (pcb_element_t **) Result2, (pcb_element_t **) Result3, pcb_true)) + return (PCB_TYPE_ELEMENT); + + return (PCB_TYPE_NONE); +} + +/* --------------------------------------------------------------------------- + * 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. + */ +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_POLYGON || type == PCB_TYPE_POLYGON_POINT) { + PCB_POLY_ALL_LOOP(Base); + { + if (polygon->ID == ID) { + *Result1 = (void *) layer; + *Result2 = *Result3 = (void *) polygon; + return (PCB_TYPE_POLYGON); + } + if (type == PCB_TYPE_POLYGON_POINT) + PCB_POLY_POINT_LOOP(polygon); + { + if (point->ID == ID) { + *Result1 = (void *) layer; + *Result2 = (void *) polygon; + *Result3 = (void *) point; + return (PCB_TYPE_POLYGON_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_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; + } + + 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; + + pcb_message(PCB_MSG_ERROR, "hace: Internal error, search for ID %d failed\n", ID); + return (PCB_TYPE_NONE); +} + +/* --------------------------------------------------------------------------- + * searches for an element by its board name. + * The function returns a pointer to the element, 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.3/src/search.h =================================================================== --- tags/1.2.3/src/search.h (nonexistent) +++ tags/1.2.3/src/search.h (revision 8969) @@ -0,0 +1,167 @@ +/* + * 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 + * + */ + +/* prototypes for search routines */ + +#ifndef PCB_SEARCH_H +#define PCB_SEARCH_H + +#include "obj_common.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 useful macros + */ +/* --------------------------------------------------------------------------- + * 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)->Y,(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_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_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_BOX_TOUCHES_BOX(&((p)->BoundingBox), (b))) + +#define PCB_ELEMENT_TOUCHES_BOX(e,b) \ + (PCB_BOX_TOUCHES_BOX(&((e)->BoundingBox), (b))) + +#define PCB_ARC_TOUCHES_BOX(a,b) \ + (PCB_BOX_TOUCHES_BOX(&((a)->BoundingBox), (b))) + + +/* == 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_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)) + + + +/* --------------------------------------------------------------------------- + * prototypes + */ +pcb_bool pcb_is_point_on_line(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_line_t *); +pcb_bool pcb_is_point_in_pin(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_pin_t *); +pcb_bool pcb_is_point_on_arc(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_arc_t *); +pcb_bool pcb_is_point_on_line_end(pcb_coord_t, pcb_coord_t, pcb_rat_t *); +pcb_bool pcb_is_line_in_rectangle(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_line_t *); +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, pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_arc_t *); +pcb_bool pcb_is_point_in_pad(pcb_coord_t, pcb_coord_t, pcb_coord_t, pcb_pad_t *); +pcb_bool pcb_is_point_in_box(pcb_coord_t, pcb_coord_t, pcb_box_t *, pcb_coord_t); + +int pcb_search_obj_by_location(unsigned, void **, void **, void **, pcb_coord_t, pcb_coord_t, pcb_coord_t); +int pcb_search_screen(pcb_coord_t, pcb_coord_t, int, void **, void **, void **); +int pcb_search_grid_slop(pcb_coord_t, pcb_coord_t, int, void **, void **, void **); +int pcb_search_obj_by_id(pcb_data_t *, void **, void **, void **, int, int); +pcb_element_t *pcb_search_elem_by_name(pcb_data_t *, const char *); + +#endif Index: tags/1.2.3/src/select.c =================================================================== --- tags/1.2.3/src/select.c (nonexistent) +++ tags/1.2.3/src/select.c (revision 8969) @@ -0,0 +1,1020 @@ +/* + * 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 + * + */ + + +/* select routines + */ + +#include "config.h" +#include "conf_core.h" + +#include "board.h" +#include "data.h" +#include "draw.h" +#include "error.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 + +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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, pad); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_undo_add_obj_to_flag(PCB_TYPE_ELEMENT_NAME, element, text, text); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, text); + } + PCB_END_LOOP; + pcb_undo_add_obj_to_flag(PCB_TYPE_ELEMENT, element, element, 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)) { + DrawElementName(element); + DrawElementPackage(element); + } + if (pcb->PinOn) + DrawElementPinsAndPads(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(PCB_TYPE_ELEMENT_NAME, element, text, text); + PCB_FLAG_CHANGE(how, PCB_FLAG_SELECTED, text); + } + PCB_END_LOOP; + + if (redraw) + DrawElementName(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, &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(PCB_TYPE_VIA, ptr1, ptr1, ptr1); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr1); + DrawVia((pcb_pin_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(PCB_TYPE_LINE, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, line); + DrawLine(layer, line); + break; + } + + case PCB_TYPE_RATLINE: + { + pcb_rat_t *rat = (pcb_rat_t *) ptr2; + + pcb_undo_add_obj_to_flag(PCB_TYPE_RATLINE, ptr1, ptr1, ptr1); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, rat); + DrawRat(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(PCB_TYPE_ARC, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, arc); + DrawArc(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(PCB_TYPE_TEXT, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, text); + DrawText(layer, text); + break; + } + + case PCB_TYPE_POLYGON: + { + pcb_polygon_t *poly = (pcb_polygon_t *) ptr2; + + layer = (pcb_layer_t *) ptr1; + pcb_undo_add_obj_to_flag(PCB_TYPE_POLYGON, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, poly); + DrawPolygon(layer, poly); + /* changing memory order no longer effects draw order */ + break; + } + + case PCB_TYPE_PIN: + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pin_t *) ptr2); + DrawPin((pcb_pin_t *) ptr2); + break; + + case PCB_TYPE_PAD: + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, ptr1, ptr2, ptr2); + PCB_FLAG_TOGGLE(PCB_FLAG_SELECTED, (pcb_pad_t *) ptr2); + DrawPad((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; + } + pcb_draw(); + pcb_undo_inc_serial(); + return (changed); +} + +/* ---------------------------------------------------------------------- + * 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. + */ +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; + +#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 (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 + +/*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(undo_type, p1, obj, 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) + DrawRat(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->On || !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->On) + DrawLine(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->On) + DrawArc(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)) + DrawText(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_POLYGON, layer, polygon); + if (layer->On) + DrawPolygon(layer, polygon); + } + } + PCB_END_LOOP; + } + 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)) + DrawElementName(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) + DrawPin(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) + DrawPad(pad); + } + } + PCB_END_LOOP; + if (pcb->PinOn) + DrawElement(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) + DrawPin(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) + DrawPad(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) + DrawVia(via); + } + } + 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 + +/* ---------------------------------------------------------------------- + * 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) +{ + /* do not list, set flag */ + return (ListBlock_(pcb, Box, Flag, NULL) == NULL) ? pcb_false : pcb_true; +} + +/* ---------------------------------------------------------------------- + * 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); +} + +/* ---------------------------------------------------------------------- + * performs several operations on the passed object + */ +#warning TODO: maybe move this to operation.c +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_POLYGON: + if (F->Polygon) + return (F->Polygon(ctx, (pcb_layer_t *) Ptr1, (pcb_polygon_t *) Ptr2)); + break; + + case PCB_TYPE_POLYGON_POINT: + if (F->Point) + return (F->Point(ctx, (pcb_layer_t *) Ptr1, (pcb_polygon_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_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_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_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(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_LINE, layer, line, 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(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, arc)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_ARC, layer, arc, 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(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, text) && pcb_text_is_visible(PCB, layer, text)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_TEXT, layer, text, 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_POLYGON && F->Polygon) + PCB_POLY_VISIBLE_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, polygon)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_POLYGON, layer, polygon, polygon); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, polygon); + } + F->Polygon(ctx, layer, polygon); + changed = pcb_true; + } + } + PCB_ENDALL_LOOP; + + /* elements silkscreen */ + if (type & PCB_TYPE_ELEMENT && pcb_silk_on(pcb) && F->Element) + PCB_ELEMENT_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_ELEMENT, element, element, 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(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, &PCB_ELEM_TEXT_VISIBLE(PCB, element))) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_ELEMENT_NAME, element, &PCB_ELEM_TEXT_VISIBLE(PCB, element), &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(pcb->Data); + { + PCB_PIN_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pin)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, element, pin, 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(pcb->Data); + { + PCB_PAD_LOOP(element); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, pad)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, pad); + } + F->Pad(ctx, element, pad); + changed = pcb_true; + } + } + PCB_END_LOOP; + } + PCB_END_LOOP; + + /* process vias */ + if (type & PCB_TYPE_VIA && pcb->ViaOn && F->Via) + PCB_VIA_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, via)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_CLEAR(PCB_FLAG_SELECTED, via); + } + F->Via(ctx, via); + changed = pcb_true; + } + } + PCB_END_LOOP; + /* and rat-lines */ + if (type & PCB_TYPE_RATLINE && pcb->RatOn && F->Rat) + PCB_RAT_LOOP(pcb->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, line)) { + if (Reset) { + pcb_undo_add_obj_to_flag(PCB_TYPE_RATLINE, line, line, 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); +} + +/* ---------------------------------------------------------------------- + * 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(PCB_TYPE_RATLINE, line, line, line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, line); + DrawRat(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(PCB_TYPE_LINE, layer, line, line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, line); + DrawLine(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(PCB_TYPE_ARC, layer, arc, arc); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, arc); + DrawArc(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(PCB_TYPE_POLYGON, layer, polygon, polygon); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, polygon); + DrawPolygon(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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + DrawPin(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(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + DrawPad(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(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, via); + DrawVia(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(PCB_TYPE_TEXT, layer, text, text); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, text); + DrawText(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(PCB_TYPE_ELEMENT, element, element, element); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, element); + PCB_PIN_LOOP(element); + { + pcb_undo_add_obj_to_flag(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + } + PCB_END_LOOP; + PCB_PAD_LOOP(element); + { + pcb_undo_add_obj_to_flag(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + } + PCB_END_LOOP; + PCB_ELEMENT_PCB_TEXT_LOOP(element); + { + pcb_undo_add_obj_to_flag(PCB_TYPE_ELEMENT_NAME, element, text, text); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, text); + } + PCB_END_LOOP; + DrawElementName(element); + DrawElement(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(PCB_TYPE_PIN, element, pin, pin); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pin); + DrawPin(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(PCB_TYPE_PAD, element, pad, pad); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, pad); + DrawPad(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(PCB_TYPE_VIA, via, via, via); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, Flag, via); + DrawVia(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.type, conn.ptr1, conn.ptr2, conn.ptr2, 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.3/src/select.h =================================================================== --- tags/1.2.3/src/select.h (nonexistent) +++ tags/1.2.3/src/select.h (revision 8969) @@ -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., 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 + * + */ + +/* prototypes for select routines */ + +#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_POLYGON | PCB_TYPE_ELEMENT | \ + PCB_TYPE_PIN | PCB_TYPE_PAD | 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); + +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_opfunc_t *F, pcb_opctx_t *ctx, pcb_bool Reset, int type); + +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.3/src/select_act.c =================================================================== --- tags/1.2.3/src/select_act.c (nonexistent) +++ tags/1.2.3/src/select_act.c (revision 8969) @@ -0,0 +1,387 @@ +/* + * 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 "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"); + + *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_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; + 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(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_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.3/src/stub_draw.c =================================================================== --- tags/1.2.3/src/stub_draw.c (nonexistent) +++ tags/1.2.3/src/stub_draw.c (revision 8969) @@ -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., 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 + * + */ +#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(); + DrawTextLowLevel(&t, 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) +{ + 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) = dummy_DrawFab; + + +/****** csect - cross section of the board ******/ + + +static void dummy_draw_csect(pcb_hid_gc_t gc) +{ + 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) = 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) +{ + 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) = 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.3/src/stub_draw.h =================================================================== --- tags/1.2.3/src/stub_draw.h (nonexistent) +++ tags/1.2.3/src/stub_draw.h (revision 8969) @@ -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., 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 + * + */ + +/* 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); + +/* csect */ +extern void (*pcb_stub_draw_csect)(pcb_hid_gc_t gc); +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); +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.3/src/stub_mincut.c =================================================================== --- tags/1.2.3/src/stub_mincut.c (nonexistent) +++ tags/1.2.3/src/stub_mincut.c (revision 8969) @@ -0,0 +1,45 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" +#include +#include "stub_mincut.h" +#include "obj_pinvia.h" +#include "obj_pad.h" + +static void stub_rat_proc_shorts_dummy(void) +{ +} + +static void stub_rat_found_short_dummy(pcb_pin_t * pin, pcb_pad_t * pad, const char *with_net) +{ + /* original behavior: just warn at random pins/pads */ + if (pin != NULL) + PCB_FLAG_SET(PCB_FLAG_WARN, pin); + if (pad != NULL) + PCB_FLAG_SET(PCB_FLAG_WARN, pad); + + stub_rat_proc_shorts_dummy(); +} + +void (*pcb_stub_rat_found_short)(pcb_pin_t * pin, pcb_pad_t * pad, 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.3/src/stub_mincut.h =================================================================== --- tags/1.2.3/src/stub_mincut.h (nonexistent) +++ tags/1.2.3/src/stub_mincut.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "global_typedefs.h" + +extern void (*pcb_stub_rat_found_short)(pcb_pin_t * pin, pcb_pad_t * pad, const char *with_net); +extern void (*pcb_stub_rat_proc_shorts)(void); + Index: tags/1.2.3/src/stub_stroke.c =================================================================== --- tags/1.2.3/src/stub_stroke.c (nonexistent) +++ tags/1.2.3/src/stub_stroke.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/stub_stroke.h =================================================================== --- tags/1.2.3/src/stub_stroke.h (nonexistent) +++ tags/1.2.3/src/stub_stroke.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/stub_vendor.c =================================================================== --- tags/1.2.3/src/stub_vendor.c (nonexistent) +++ tags/1.2.3/src/stub_vendor.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/stub_vendor.h =================================================================== --- tags/1.2.3/src/stub_vendor.h (nonexistent) +++ tags/1.2.3/src/stub_vendor.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src/undo.c =================================================================== --- tags/1.2.3/src/undo.c (nonexistent) +++ tags/1.2.3/src/undo.c (revision 8969) @@ -0,0 +1,1670 @@ +/* + * 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 + * + */ + +/* 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 "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 "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 + + +static pcb_bool between_increment_and_restore = pcb_false; +static pcb_bool added_undo_between_increment_and_restore = pcb_false; + +/* --------------------------------------------------------------------------- + * some local data types + */ +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; + } Data; +} UndoListType, *UndoListTypePtr; + +/* --------------------------------------------------------------------------- + * some local variables + */ +static pcb_data_t *RemoveList = NULL; /* list of removed objects */ +static UndoListTypePtr UndoList = NULL; /* list of operations */ +static int Serial = 1, /* serial number */ + SavedSerial; +static size_t UndoN, RedoN, /* number of entries */ + UndoMax; +static pcb_bool Locked = pcb_false; /* do not add entries if */ +static pcb_bool andDraw = pcb_true; + /* flag is set; prevents from */ + /* infinite loops */ + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +static UndoListTypePtr GetUndoSlot(int, int, int); +static void DrawRecoveredObject(int, void *, void *, void *); +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 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 int PerformUndo(UndoListTypePtr); + +/* --------------------------------------------------------------------------- + * adds a command plus some data to the undo list + */ +static UndoListTypePtr GetUndoSlot(int CommandType, int ID, int Kind) +{ + UndoListTypePtr ptr; + void *ptr1, *ptr2, *ptr3; + int type; + size_t limit = ((size_t)conf_core.editor.undo_warning_size) * 1024; + +#ifdef DEBUG_ID + if (pcb_search_obj_by_id(PCB->Data, &ptr1, &ptr2, &ptr3, ID, Kind) == PCB_TYPE_NONE) + pcb_message(PCB_MSG_ERROR, "hace: ID (%d) and Type (%x) mismatch in AddObject...\n", ID, Kind); +#endif + + /* allocate memory */ + if (UndoN >= UndoMax) { + size_t size; + + UndoMax += STEP_UNDOLIST; + size = UndoMax * sizeof(UndoListType); + UndoList = (UndoListTypePtr) realloc(UndoList, size); + memset(&UndoList[UndoN], 0, STEP_REMOVELIST * sizeof(UndoListType)); + + /* ask user to flush the table because of it's size */ + if (size > limit) { + size_t l2; + l2 = (size / limit + 1) * limit; + pcb_message(PCB_MSG_INFO, _("Size of 'undo-list' exceeds %li kb\n"), (long) (l2 >> 10)); + } + } + + /* free structures from the pruned redo list */ + + for (ptr = &UndoList[UndoN]; RedoN; ptr++, RedoN--) + 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(RemoveList, &ptr1, &ptr2, &ptr3, ptr->ID, ptr->Kind); + if (type != PCB_TYPE_NONE) { + pcb_destroy_object(RemoveList, type, ptr1, ptr2, ptr3); + } + break; + default: + break; + } + + if (between_increment_and_restore) + added_undo_between_increment_and_restore = pcb_true; + + /* copy typefield and serial number to the list */ + ptr = &UndoList[UndoN++]; + ptr->Type = CommandType; + ptr->Kind = Kind; + ptr->ID = ID; + ptr->Serial = Serial; + return (ptr); +} + +/* --------------------------------------------------------------------------- + * redraws the recovered object + */ +static void DrawRecoveredObject(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + if (Type & (PCB_TYPE_LINE | PCB_TYPE_TEXT | PCB_TYPE_POLYGON | PCB_TYPE_ARC)) { + pcb_layer_t *layer; + + layer = LAYER_PTR(pcb_layer_id(RemoveList, (pcb_layer_t *) Ptr1)); + pcb_draw_obj(Type, (void *) layer, Ptr2); + } + else + pcb_draw_obj(Type, Ptr1, Ptr2); +} + +/* --------------------------------------------------------------------------- + * recovers an object from a '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_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 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 (andDraw) + pcb_erase_obj(type, ptr1, ptr2); + ((pcb_pin_t *) ptr2)->DrillingHole = Entry->Data.Size; + Entry->Data.Size = swap; + pcb_draw_obj(type, ptr1, 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 (andDraw) + 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(type, ptr1, 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 (andDraw) + 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(type, ptr1, 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 (andDraw) + 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 (andDraw) + pcb_draw_obj(type, ptr1, 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 (andDraw) + 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 (andDraw) + pcb_draw_obj(type, ptr1, 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 ((andDraw) && (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 (andDraw) + pcb_draw_obj(type, ptr1, 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 (andDraw && must_redraw && (ptr1e != NULL)) + pcb_erase_obj(type, ptr1e, ptr2); + + pin->Flags = Entry->Data.Flags; + + Entry->Data.Flags = swap; + + if (andDraw && must_redraw) + pcb_draw_obj(type, ptr1, 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)); + 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 (andDraw) + EraseElement(element); + pcb_element_mirror(PCB->Data, element, Entry->Data.Move.DY); + if (andDraw) + DrawElement(element); + return (pcb_true); + } + pcb_message(PCB_MSG_ERROR, "hace Internal error: UndoMirror on object type %d\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 (!RemoveList) + RemoveList = pcb_buffer_new(PCB); + if (andDraw) + pcb_erase_obj(type, ptr1, ptr2); + /* in order to make this re-doable we move it to the RemoveList */ + pcb_move_obj_to_buffer(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(RemoveList, &ptr1, &ptr2, &ptr3, Entry->ID, Entry->Kind); + if (type != PCB_TYPE_NONE) { + if (andDraw) + DrawRecoveredObject(type, ptr1, ptr2, ptr3); + pcb_move_obj_to_buffer(PCB, PCB->Data, RemoveList, type, ptr1, ptr2, ptr3); + 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_polygon_t *polygon; + void *ptr3; + int type; + + /* lookup entry (polygon not point was saved) by it's ID */ + assert(Entry->Kind == PCB_TYPE_POLYGON); + type = pcb_search_obj_by_id(PCB->Data, (void **) &layer, (void **) &polygon, &ptr3, Entry->ID, Entry->Kind); + switch (type) { + case PCB_TYPE_POLYGON: /* restore the removed point */ + { + /* recover the point */ + if (andDraw && layer->On) + ErasePolygon(polygon); + pcb_insert_point_in_object(PCB_TYPE_POLYGON, 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 (andDraw && layer->On) + DrawPolygon(layer, polygon); + Entry->Type = PCB_UNDO_INSERT_POINT; + Entry->ID = Entry->Data.RemovedPoint.ID; + Entry->Kind = PCB_TYPE_POLYGON_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_polygon_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_POLYGON_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_POLYGON_POINT: /* removes an inserted polygon point */ + { + if (andDraw && layer->On) + ErasePolygon(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_POLYGON; + Entry->Type = PCB_UNDO_REMOVE_POINT; + Entry->Data.RemovedPoint.Index = point_idx; + pcb_destroy_object(PCB->Data, PCB_TYPE_POLYGON_POINT, layer, polygon, pnt); + if (andDraw && layer->On) + DrawPolygon(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(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, RemoveList, PCB->Data, type, ptr1b, ptr2b, ptr3b); + + if (andDraw) + DrawRecoveredObject(Entry->Kind, ptr1, ptr2, ptr3); + + obj = (pcb_any_obj_t *) pcb_move_obj_to_buffer(PCB, PCB->Data, RemoveList, type, ptr1, ptr2, ptr3); + if (Entry->Kind == PCB_TYPE_POLYGON) + pcb_poly_init_clip(PCB->Data, (pcb_layer_t *) ptr1b, (pcb_polygon_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_POLYGON); + return UndoSwapCopiedObject(Entry); +} + +/* --------------------------------------------------------------------------- + * recovers an inserted polygon point + * returns pcb_true on success + */ +static pcb_bool UndoInsertContour(UndoListTypePtr Entry) +{ + assert(Entry->Kind == PCB_TYPE_POLYGON); + 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(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; +} + +/* --------------------------------------------------------------------------- + * undo of any 'hard to recover' operation + * + * returns the bitfield for the types of operations that were undone + */ +int pcb_undo(pcb_bool draw) +{ + UndoListTypePtr ptr; + int Types = 0; + int unique; + pcb_bool error_undoing = pcb_false; + + unique = conf_core.editor.unique_names; + conf_force_set_bool(conf_core.editor.unique_names, 0); + + andDraw = draw; + + if (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 0; + } + + if (UndoN == 0) { + pcb_message(PCB_MSG_INFO, _("Nothing to undo - buffer is empty\n")); + return 0; + } + + Serial--; + + ptr = &UndoList[UndoN - 1]; + + if (ptr->Serial > 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"), ptr->Serial, 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. + */ + Serial = ptr->Serial + 1; + return 0; + } + + pcb_undo_lock(); /* lock undo module to prevent from loops */ + + /* Loop over all entries with the correct serial number */ + for (; UndoN && ptr->Serial == Serial; ptr--, UndoN--, RedoN++) { + int undid = PerformUndo(ptr); + if (undid == 0) + error_undoing = pcb_true; + Types |= undid; + } + + pcb_undo_unlock(); + + if (error_undoing) + pcb_message(PCB_MSG_ERROR, _("ERROR: Failed to undo some operations\n")); + + if (Types && andDraw) + pcb_draw(); + + /* restore the unique flag setting */ + conf_force_set_bool(conf_core.editor.unique_names, unique); + + return Types; +} + +static int PerformUndo(UndoListTypePtr ptr) +{ + switch (ptr->Type) { + case PCB_UNDO_CHANGENAME: + if (UndoChangeName(ptr)) + return (PCB_UNDO_CHANGENAME); + break; + + case PCB_UNDO_CHANGEPINNUM: + if (UndoChangePinnum(ptr)) + return (PCB_UNDO_CHANGEPINNUM); + break; + + case PCB_UNDO_CREATE: + if (UndoCopyOrCreate(ptr)) + return (PCB_UNDO_CREATE); + break; + + case PCB_UNDO_MOVE: + if (UndoMove(ptr)) + return (PCB_UNDO_MOVE); + break; + + case PCB_UNDO_REMOVE: + if (UndoRemove(ptr)) + return (PCB_UNDO_REMOVE); + break; + + case PCB_UNDO_REMOVE_POINT: + if (UndoRemovePoint(ptr)) + return (PCB_UNDO_REMOVE_POINT); + break; + + case PCB_UNDO_INSERT_POINT: + if (UndoInsertPoint(ptr)) + return (PCB_UNDO_INSERT_POINT); + break; + + case PCB_UNDO_REMOVE_CONTOUR: + if (UndoRemoveContour(ptr)) + return (PCB_UNDO_REMOVE_CONTOUR); + break; + + case PCB_UNDO_INSERT_CONTOUR: + if (UndoInsertContour(ptr)) + return (PCB_UNDO_INSERT_CONTOUR); + break; + + case PCB_UNDO_ROTATE: + if (UndoRotate(ptr)) + return (PCB_UNDO_ROTATE); + break; + + case PCB_UNDO_CLEAR: + if (UndoClearPoly(ptr)) + return (PCB_UNDO_CLEAR); + break; + + case PCB_UNDO_MOVETOLAYER: + if (UndoMoveToLayer(ptr)) + return (PCB_UNDO_MOVETOLAYER); + break; + + case PCB_UNDO_FLAG: + if (UndoFlag(ptr)) + return (PCB_UNDO_FLAG); + break; + + case PCB_UNDO_CHANGESIZE: + if (UndoChangeSize(ptr)) + return (PCB_UNDO_CHANGESIZE); + break; + + case PCB_UNDO_CHANGECLEARSIZE: + if (UndoChangeClearSize(ptr)) + return (PCB_UNDO_CHANGECLEARSIZE); + break; + + case PCB_UNDO_CHANGEMASKSIZE: + if (UndoChangeMaskSize(ptr)) + return (PCB_UNDO_CHANGEMASKSIZE); + break; + + case PCB_UNDO_CHANGE2NDSIZE: + if (UndoChange2ndSize(ptr)) + return (PCB_UNDO_CHANGE2NDSIZE); + break; + + case PCB_UNDO_CHANGEANGLES: + if (UndoChangeAngles(ptr)) + return (PCB_UNDO_CHANGEANGLES); + break; + + case PCB_UNDO_CHANGERADII: + if (UndoChangeRadii(ptr)) + return (PCB_UNDO_CHANGERADII); + break; + + case PCB_UNDO_LAYERMOVE: + if (UndoLayerMove(ptr)) + return (PCB_UNDO_LAYERMOVE); + break; + + case PCB_UNDO_NETLISTCHANGE: + if (UndoNetlistChange(ptr)) + return (PCB_UNDO_NETLISTCHANGE); + break; + + case PCB_UNDO_MIRROR: + if (UndoMirror(ptr)) + return (PCB_UNDO_MIRROR); + break; + } + return 0; +} + +/* --------------------------------------------------------------------------- + * redo of any 'hard to recover' operation + * + * returns the number of operations redone + */ +int pcb_redo(pcb_bool draw) +{ + UndoListTypePtr ptr; + int Types = 0; + pcb_bool error_undoing = pcb_false; + + andDraw = draw; + + if (RedoN == 0) { + pcb_message(PCB_MSG_INFO, _("Nothing to redo. Perhaps changes have been made since last undo\n")); + return 0; + } + + ptr = &UndoList[UndoN]; + + if (ptr->Serial < 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"), ptr->Serial, 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. + */ + Serial = ptr->Serial; + return 0; + } + + pcb_undo_lock(); /* lock undo module to prevent from loops */ + + /* and loop over all entries with the correct serial number */ + for (; RedoN && ptr->Serial == Serial; ptr++, UndoN++, RedoN--) { + int undid = PerformUndo(ptr); + if (undid == 0) + error_undoing = pcb_true; + Types |= undid; + } + + /* Make next serial number current */ + Serial++; + + pcb_undo_unlock(); + + if (error_undoing) + pcb_message(PCB_MSG_ERROR, _("ERROR: Failed to redo some operations\n")); + + if (Types && andDraw) + pcb_draw(); + + return Types; +} + +/* --------------------------------------------------------------------------- + * 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; + Serial = SavedSerial; +} + +/* --------------------------------------------------------------------------- + * 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; + SavedSerial = Serial; +} + +/* --------------------------------------------------------------------------- + * 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 (UndoN > 0 && UndoList[UndoN - 1].Serial == Serial) + pcb_board_set_changed_flag(pcb_true); + Serial++; + 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) +{ + UndoListTypePtr undo; + + if (UndoN && (Force || pcb_gui->confirm_dialog("OK to clear 'undo' buffer?", 0))) { + /* release memory allocated by objects in undo list */ + for (undo = UndoList; UndoN; undo++, UndoN--) { + if ((undo->Type == PCB_UNDO_CHANGENAME) || (undo->Type == PCB_UNDO_CHANGEPINNUM)) + free(undo->Data.ChangeName.Name); + } + free(UndoList); + UndoList = NULL; + if (RemoveList) { + pcb_data_free(RemoveList); + free(RemoveList); + RemoveList = NULL; + } + + /* reset some counters */ + UndoN = UndoMax = RedoN = 0; + } + + /* reset counter in any case */ + Serial = 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 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_uint8_t Steps) +{ + 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.Rotate.Steps = Steps; + } +} + +/* --------------------------------------------------------------------------- + * 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 (!RemoveList) + RemoveList = pcb_buffer_new(PCB); + + GetUndoSlot(PCB_UNDO_REMOVE, PCB_OBJECT_ID(Ptr3), Type); + pcb_move_obj_to_buffer(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_polygon_t *polygon = (pcb_polygon_t *) Ptr2; + pcb_cardinal_t hole; + pcb_bool last_in_contour = pcb_false; + + if (!Locked) { + switch (Type) { + case PCB_TYPE_POLYGON_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_POLYGON); + 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 (!RemoveList) + RemoveList = pcb_buffer_new(PCB); + + undo = GetUndoSlot(undo_type, PCB_OBJECT_ID(Ptr2), Type); + copy = (pcb_any_obj_t *) pcb_copy_obj_to_buffer(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_polygon_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_polygon_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 + */ +void pcb_undo_add_obj_to_flag(int Type, void *Ptr1, void *Ptr2, void *Ptr3) +{ + UndoListTypePtr undo; + + if (!Locked) { + undo = GetUndoSlot(PCB_UNDO_FLAG, PCB_OBJECT_ID(Ptr2), Type); + undo->Data.Flags = ((pcb_pin_t *) Ptr2)->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; + + + } + } + + } +} + +/* --------------------------------------------------------------------------- + * 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); +} + +#ifndef NDEBUG +static 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_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_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; +} + +void undo_dump(void) +{ + size_t n; + int last_serial = -2; + printf("Serial=%d\n", Serial); + for(n = 0; n < UndoN; n++) { + if (last_serial != UndoList[n].Serial) { + printf("--- serial=%d\n", UndoList[n].Serial); + last_serial = UndoList[n].Serial; + } + printf(" type=%s kind=%d ID=%d\n", undo_type2str(UndoList[n].Type), UndoList[n].Kind, UndoList[n].ID); + } +} + +#endif Index: tags/1.2.3/src/undo.h =================================================================== --- tags/1.2.3/src/undo.h (nonexistent) +++ tags/1.2.3/src/undo.h (revision 8969) @@ -0,0 +1,107 @@ +/* + * 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 + * + */ + +/* prototypes for undo routines */ + +#ifndef PCB_UNDO_H +#define PCB_UNDO_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 */ + +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_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_polygon_t *); +void pcb_undo_add_obj_to_insert_contour(int, pcb_layer_t *, pcb_polygon_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_rotate(int, void *, void *, void *, pcb_coord_t, pcb_coord_t, pcb_uint8_t); +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_obj_to_move_to_layer(int, void *, void *, void *); +void pcb_undo_add_obj_to_flag(int, void *, void *, void *); +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 *); + +void pcb_undo_lock(void); +void pcb_undo_unlock(void); +pcb_bool pcb_undoing(void); + +/* 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); + +/* --------------------------------------------------------------------------- + * 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_ROTATE = 0x000080, /* rotations */ + 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_op_t; + +#endif Index: tags/1.2.3/src/undo_act.c =================================================================== --- tags/1.2.3/src/undo_act.c (nonexistent) +++ tags/1.2.3/src/undo_act.c (revision 8969) @@ -0,0 +1,297 @@ +/* + * 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 "polygon.h" +#include "search.h" + +#include "obj_line_draw.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[] = "pcb_undo()\n" "pcb_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) { + /* don't allow undo in the middle of an operation */ + if (conf_core.editor.mode != PCB_MODE_POLYGON_HOLE && pcb_crosshair.AttachedObject.State != PCB_CH_STATE_FIRST) + return 1; + if (pcb_crosshair.AttachedBox.State != PCB_CH_STATE_FIRST && conf_core.editor.mode != PCB_MODE_ARC) + return 1; + /* undo the last operation */ + + pcb_notify_crosshair_change(pcb_false); + if ((conf_core.editor.mode == PCB_MODE_POLYGON || conf_core.editor.mode == PCB_MODE_POLYGON_HOLE) && pcb_crosshair.AttachedPolygon.PointN) { + pcb_polygon_go_to_prev_point(); + pcb_notify_crosshair_change(pcb_true); + return 0; + } + /* move anchor point if undoing during line creation */ + if (conf_core.editor.mode == PCB_MODE_LINE) { + 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); + pcb_notify_crosshair_change(pcb_true); + return 0; + } + if (pcb_crosshair.AttachedLine.State == PCB_CH_STATE_THIRD) { + int type; + void *ptr1, *ptr3, *ptrtmp; + pcb_line_t *ptr2; + /* 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))) + 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; + pcb_notify_crosshair_change(pcb_true); + return 0; + } + /* 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); + DrawLine(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; + lastLayer = 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; + lastLayer = (pcb_layer_t *) ptr1; + } + pcb_notify_crosshair_change(pcb_true); + return 0; + } + } + if (conf_core.editor.mode == PCB_MODE_ARC) { + if (pcb_crosshair.AttachedBox.State == PCB_CH_STATE_SECOND) { + pcb_crosshair.AttachedBox.State = PCB_CH_STATE_FIRST; + pcb_notify_crosshair_change(pcb_true); + return 0; + } + 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; + } + } + /* undo the last destructive operation */ + if (pcb_undo(pcb_true)) + 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[] = "pcb_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) +{ + if (((conf_core.editor.mode == PCB_MODE_POLYGON || + conf_core.editor.mode == PCB_MODE_POLYGON_HOLE) && pcb_crosshair.AttachedPolygon.PointN) || pcb_crosshair.AttachedLine.State == PCB_CH_STATE_SECOND) + return 1; + pcb_notify_crosshair_change(pcb_false); + if (pcb_redo(pcb_true)) { + pcb_board_set_changed_flag(pcb_true); + if (conf_core.editor.mode == PCB_MODE_LINE && 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++; + } + } + 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.3/src/unit.c =================================================================== --- tags/1.2.3/src/unit.c (nonexistent) +++ tags/1.2.3/src/unit.c (revision 8969) @@ -0,0 +1,292 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 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, "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 Units / sizeof Units[0])) +/* \brief Initialize non-static data for pcb-printf + * \par Function Description + * 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) +{ + int i; + for (i = 0; i < N_UNITS; ++i) { + Units[i].index = i; + Units[i].in_suffix = _(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 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)}, + {"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 increments / sizeof increments[0]) + +/* \brief Obtain a unit object from its suffix + * \par Function Description + * Looks up a given suffix in the main units array. Internationalized + * unit suffixes are not supported, though pluralized units are, for + * backward-compatibility. + * + * \param [in] const_suffix The suffix to look up + * + * \return A const pointer to the pcb_unit_t struct, or NULL if none was found + */ +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, Units[i].suffix, s_len) == 0 || strncmp(suffix, Units[i].alias[0], s_len) == 0) + return &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 (Units[i].allow == allow) + return &Units[i]; + + return NULL; +} + +/* ACCESSORS */ +/* \brief Returns the master unit list. This may not be modified. */ +const pcb_unit_t *get_unit_list(void) +{ + return Units; +} + +/* \brief Returns the unit by its index */ +const pcb_unit_t *get_unit_by_idx(int idx) +{ + if ((idx < 0) || (idx >= N_UNITS)) + return NULL; + return Units + idx; +} + +/* \brief Returns the length of the master unit list. */ +int pcb_get_n_units(void) +{ + return N_UNITS; +} + +/* \brief Convert a pcb coord to the given unit + * + * \param [in] unit The unit to convert to + * \param [in] x The quantity to convert + * + * \return The converted measure + */ +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; +} + +/* \brief Convert a given unit to pcb coords + * + * \param [in] unit The unit to convert from + * \param [in] x The quantity to convert + * + * \return The converted measure + */ +pcb_coord_t pcb_unit_to_coord(const pcb_unit_t * unit, double x) +{ + double base; + if (unit == NULL) + return -1; + base = unit->family == PCB_UNIT_METRIC ? PCB_MM_TO_COORD(x) + : PCB_MIL_TO_COORD(x); + return pcb_round(base/unit->scale_factor); +} + +/* \brief Return how many PCB-internal-Coord-unit a unit translates to + * + * \param [in] unit The unit to convert + * + * \return The converted measure + */ +double pcb_unit_to_factor(const pcb_unit_t * unit) +{ + return 1.0 / pcb_coord_to_unit(unit, 1); +} + +/* \brief Obtain an increment object from its suffix + * \par Function Description + * Looks up a given suffix in the main increments array. Internationalized + * unit suffixes are not supported, nor are pluralized units. + * + * \param [in] suffix The suffix to look up + * + * \return A const pointer to the pcb_increments_t struct, or NULL if none was found + */ +pcb_increments_t *pcb_get_increments_struct(const char *suffix) +{ + int i; + /* Do lookup */ + for (i = 0; i < N_INCREMENTS; ++i) + if (strcmp(suffix, increments[i].suffix) == 0) + return &increments[i]; + return NULL; +} + +/* Bring an angle into [0, 360) range */ +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.3/src/unit.h =================================================================== --- tags/1.2.3/src/unit.h (nonexistent) +++ tags/1.2.3/src/unit.h (revision 8969) @@ -0,0 +1,139 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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_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, + + 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 Units[]; +extern pcb_increments_t increments[]; + +const pcb_unit_t *get_unit_struct(const char *suffix); +const pcb_unit_t *get_unit_struct_by_allow(enum pcb_allow_e allow); +const pcb_unit_t *get_unit_list(void); +const pcb_unit_t *get_unit_by_idx(int idx); +int pcb_get_n_units(void); +double pcb_coord_to_unit(const pcb_unit_t *, pcb_coord_t); +double pcb_unit_to_factor(const pcb_unit_t * unit); +pcb_coord_t pcb_unit_to_coord(const pcb_unit_t *, double); +pcb_increments_t *pcb_get_increments_struct(const char *suffix); +pcb_angle_t pcb_normalize_angle(pcb_angle_t a); + +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.3/src/vtlibrary.c =================================================================== --- tags/1.2.3/src/vtlibrary.c (nonexistent) +++ tags/1.2.3/src/vtlibrary.c (revision 8969) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtlibrary.h" +#include Index: tags/1.2.3/src/vtlibrary.h =================================================================== --- tags/1.2.3/src/vtlibrary.h (nonexistent) +++ tags/1.2.3/src/vtlibrary.h (revision 8969) @@ -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.3/src/vtonpoint.c =================================================================== --- tags/1.2.3/src/vtonpoint.c (nonexistent) +++ tags/1.2.3/src/vtonpoint.c (revision 8969) @@ -0,0 +1,6 @@ +#define GVT_DONT_UNDEF + +#warning TODO: this should be replaced with pcb_obj_t + +#include "vtonpoint.h" +#include Index: tags/1.2.3/src/vtonpoint.h =================================================================== --- tags/1.2.3/src/vtonpoint.h (nonexistent) +++ tags/1.2.3/src/vtonpoint.h (revision 8969) @@ -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.3/src/vtptr.c =================================================================== --- tags/1.2.3/src/vtptr.c (nonexistent) +++ tags/1.2.3/src/vtptr.c (revision 8969) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtptr.h" +#include Index: tags/1.2.3/src/vtptr.h =================================================================== --- tags/1.2.3/src/vtptr.h (nonexistent) +++ tags/1.2.3/src/vtptr.h (revision 8969) @@ -0,0 +1,35 @@ +#include +#include + +typedef void *pcb_ptr_t; + +/* Elem=void *; init=none */ + +/* all public symbols are wrapped in GVT() - see vt_t(7) */ +#define GVT(x) vtptr_ ## x + +/* Array elem type - see vt_t(7) */ +#define GVT_ELEM_TYPE pcb_ptr_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 256 + +/* Initial array size when the first element is written */ +#define GVT_START_SIZE 32 + +/* Optional prefix for function definitions (e.g. static inline) */ +#define GVT_FUNC + + +/* 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 Index: tags/1.2.3/src/vtroutestyle.c =================================================================== --- tags/1.2.3/src/vtroutestyle.c (nonexistent) +++ tags/1.2.3/src/vtroutestyle.c (revision 8969) @@ -0,0 +1,3 @@ +#define GVT_DONT_UNDEF +#include "vtroutestyle.h" +#include Index: tags/1.2.3/src/vtroutestyle.h =================================================================== --- tags/1.2.3/src/vtroutestyle.h (nonexistent) +++ tags/1.2.3/src/vtroutestyle.h (revision 8969) @@ -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.3/src =================================================================== --- tags/1.2.3/src (nonexistent) +++ tags/1.2.3/src (revision 8969) Property changes on: tags/1.2.3/src ___________________________________________________________________ Added: svn:externals ## -0,0 +1 ## + Index: tags/1.2.3/src_3rd/Makefile.conf =================================================================== --- tags/1.2.3/src_3rd/Makefile.conf (nonexistent) +++ tags/1.2.3/src_3rd/Makefile.conf (revision 8969) @@ -0,0 +1 @@ +# placeholder for genvector Index: tags/1.2.3/src_3rd/README =================================================================== --- tags/1.2.3/src_3rd/README (nonexistent) +++ tags/1.2.3/src_3rd/README (revision 8969) @@ -0,0 +1 @@ +3rd party software libs Index: tags/1.2.3/src_3rd/qparse/Makefile =================================================================== --- tags/1.2.3/src_3rd/qparse/Makefile (nonexistent) +++ tags/1.2.3/src_3rd/qparse/Makefile (revision 8969) @@ -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.3/src_3rd/qparse/example.c =================================================================== --- tags/1.2.3/src_3rd/qparse/example.c (nonexistent) +++ tags/1.2.3/src_3rd/qparse/example.c (revision 8969) @@ -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.3/src_3rd/qparse/qparse.c =================================================================== --- tags/1.2.3/src_3rd/qparse/qparse.c (nonexistent) +++ tags/1.2.3/src_3rd/qparse/qparse.c (revision 8969) @@ -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.3/src_3rd/qparse/qparse.h =================================================================== --- tags/1.2.3/src_3rd/qparse/qparse.h (nonexistent) +++ tags/1.2.3/src_3rd/qparse/qparse.h (revision 8969) @@ -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.3/src_3rd =================================================================== --- tags/1.2.3/src_3rd (nonexistent) +++ tags/1.2.3/src_3rd (revision 8969) Property changes on: tags/1.2.3/src_3rd ___________________________________________________________________ Added: svn:externals ## -0,0 +1,8 ## +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 Index: tags/1.2.3/src_plugins/Buildin.tmpasm =================================================================== --- tags/1.2.3/src_plugins/Buildin.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/Buildin.tmpasm (revision 8969) @@ -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.3/src_plugins/Common_enabled.tmpasm =================================================================== --- tags/1.2.3/src_plugins/Common_enabled.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/Common_enabled.tmpasm (revision 8969) @@ -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.3/src_plugins/Disable.tmpasm =================================================================== --- tags/1.2.3/src_plugins/Disable.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/Disable.tmpasm (revision 8969) @@ -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.3/src_plugins/Plugin.tmpasm =================================================================== --- tags/1.2.3/src_plugins/Plugin.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/Plugin.tmpasm (revision 8969) @@ -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.3/src_plugins/README =================================================================== --- tags/1.2.3/src_plugins/README (nonexistent) +++ tags/1.2.3/src_plugins/README (revision 8969) @@ -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.3/src_plugins/acompnet/Makefile =================================================================== --- tags/1.2.3/src_plugins/acompnet/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/acompnet/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_acompnet + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/acompnet/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/acompnet/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/acompnet/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/acompnet/acompnet.c =================================================================== --- tags/1.2.3/src_plugins/acompnet/acompnet.c (nonexistent) +++ tags/1.2.3/src_plugins/acompnet/acompnet.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src_plugins/acompnet/acompnet.pup =================================================================== --- tags/1.2.3/src_plugins/acompnet/acompnet.pup (nonexistent) +++ tags/1.2.3/src_plugins/acompnet/acompnet.pup (revision 8969) @@ -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.3/src_plugins/autocrop/Makefile =================================================================== --- tags/1.2.3/src_plugins/autocrop/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/autocrop/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autocrop + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/autocrop/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/autocrop/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/autocrop/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/autocrop/autocrop.c =================================================================== --- tags/1.2.3/src_plugins/autocrop/autocrop.c (nonexistent) +++ tags/1.2.3/src_plugins/autocrop/autocrop.c (revision 8969) @@ -0,0 +1,248 @@ +/*! + * \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. + * + * 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 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_polygon_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_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_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_POLYGON, 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); /* 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, NULL, NULL} +}; + +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.3/src_plugins/autocrop/autocrop.pup =================================================================== --- tags/1.2.3/src_plugins/autocrop/autocrop.pup (nonexistent) +++ tags/1.2.3/src_plugins/autocrop/autocrop.pup (revision 8969) @@ -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.3/src_plugins/autoplace/Makefile =================================================================== --- tags/1.2.3/src_plugins/autoplace/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoplace + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/autoplace/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/autoplace/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/autoplace/action.c =================================================================== --- tags/1.2.3/src_plugins/autoplace/action.c (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/action.c (revision 8969) @@ -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.3/src_plugins/autoplace/autoplace.c =================================================================== --- tags/1.2.3/src_plugins/autoplace/autoplace.c (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/autoplace.c (revision 8969) @@ -0,0 +1,771 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "board.h" +#include "vtptr.h" + + +#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) + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +static double ComputeCost(pcb_netlist_t *Nets, double T0, double T); + +/* --------------------------------------------------------------------------- + * some local types + */ +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_element_t *element; + enum ewhich which; + pcb_coord_t DX, DY; /* for shift */ + unsigned rotate; /* for rotate/flip */ + pcb_element_t *other; /* for exchange */ +} PerturbationType; + +/* --------------------------------------------------------------------------- + * some local identifiers + */ + +/* --------------------------------------------------------------------------- + * 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->type) { + case PCB_TYPE_PAD: + c->group = PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (pcb_element_t *) c->ptr1) + ? SLayer : CLayer; + c->X = ((pcb_pad_t *) c->ptr2)->Point1.X; + c->Y = ((pcb_pad_t *) c->ptr2)->Point1.Y; + break; + case PCB_TYPE_PIN: + c->group = SLayer; /* any layer will do */ + c->X = ((pcb_pin_t *) c->ptr2)->X; + c->Y = ((pcb_pin_t *) c->ptr2)->Y; + break; + default: + pcb_message(PCB_MSG_ERROR, "Odd connection type encountered in " "UpdateXY"); + break; + } + } + } +} + +/* --------------------------------------------------------------------------- + * Create a list of selected elements. + */ +static vtptr_t collectSelectedElements() +{ + vtptr_t list; + + vtptr_init(&list); + PCB_ELEMENT_LOOP(PCB->Data); + { + if (PCB_FLAG_TEST(PCB_FLAG_SELECTED, element)) { + pcb_element_t **epp = (pcb_element_t **)vtptr_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].type == PCB_TYPE_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->type != PCB_TYPE_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; + pcb_box_list_t *otherside; + pcb_box_t *box; + pcb_box_t *lastbox = NULL; + pcb_coord_t thickness; + pcb_coord_t 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; + /* 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 */ + vtptr_t seboxes, ceboxes; + struct ebox { + pcb_box_t box; + pcb_element_t *element; + }; + 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; + + vtptr_init(&seboxes); + vtptr_init(&ceboxes); + + PCB_ELEMENT_LOOP(PCB->Data); + { + boxpp = (struct ebox **) vtptr_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)->element = element; + } + PCB_END_LOOP; + rt_s = pcb_r_create_tree((const pcb_box_t **) seboxes.array, vtptr_len(&seboxes), 1); + rt_c = pcb_r_create_tree((const pcb_box_t **) ceboxes.array, vtptr_len(&ceboxes), 1); + vtptr_uninit(&seboxes); + vtptr_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->element->Name[0].TextString && 0 == PCB_NSTRCMP(element->Name[0].TextString, boxp->element->Name[0].TextString)) { + delta4 += CostParameter.matching_neighbor_bonus; + factor++; + } + if (element->Name[0].Direction == boxp->element->Name[0].Direction) + delta4 += factor * CostParameter.oriented_neighbor_bonus; + if (element->VBox.X1 == boxp->element->VBox.X1 || + element->VBox.X1 == boxp->element->VBox.X2 || + element->VBox.X2 == boxp->element->VBox.X1 || + element->VBox.X2 == boxp->element->VBox.X2 || + element->VBox.Y1 == boxp->element->VBox.Y1 || + element->VBox.Y1 == boxp->element->VBox.Y2 || + element->VBox.Y2 == boxp->element->VBox.Y1 || element->VBox.Y2 == boxp->element->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; + 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); +} + +/* --------------------------------------------------------------------------- + * 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(vtptr_t *selected, double T) +{ + PerturbationType pt = { 0 }; + /* pick element to perturb */ + pt.element = (pcb_element_t *) selected->array[pcb_rand() % vtptr_len(selected)]; + /* exchange, flip/rotate or shift? */ + switch (pcb_rand() % ((vtptr_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 */ + pt.DX = MAX(pt.DX, -pt.element->VBox.X1); + pt.DX = MIN(pt.DX, PCB->MaxWidth - pt.element->VBox.X2); + pt.DY = MAX(pt.DY, -pt.element->VBox.Y1); + pt.DY = MIN(pt.DY, PCB->MaxHeight - pt.element->VBox.Y2); + /* all done but the movin' */ + break; + } + case 1: + { /* flip/rotate! */ + /* only flip if it's an SMD component */ + pcb_bool isSMD = padlist_length(&(pt.element->Pad)) != 0; + 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_element_t *) + selected->array[pcb_rand() % (vtptr_len(selected) - 1)]; + if (pt.other == pt.element) + pt.other = (pcb_element_t *) selected->array[vtptr_len(selected) - 1]; + /* don't allow exchanging a solderside-side SMD component + * with a non-SMD component. */ + if ((pinlist_length(&(pt.element->Pin)) != 0 /* non-SMD */ && + PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pt.other)) || (pinlist_length(&pt.other->Pin) != 0 /* non-SMD */ && + PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pt.element))) + return createPerturbation(selected, T); + break; + } + default: + assert(0); + } + return pt; +} + +void doPerturb(PerturbationType * pt, pcb_bool undo) +{ + pcb_coord_t bbcx, bbcy; + /* compute center of element bounding box */ + bbcx = (pt->element->VBox.X1 + pt->element->VBox.X2) / 2; + bbcy = (pt->element->VBox.Y1 + pt->element->VBox.Y2) / 2; + /* do exchange, shift or flip/rotate */ + switch (pt->which) { + case SHIFT: + { + pcb_coord_t DX = pt->DX, DY = pt->DY; + if (undo) { + DX = -DX; + DY = -DY; + } + pcb_element_move(PCB->Data, pt->element, DX, DY); + return; + } + case ROTATE: + { + unsigned b = pt->rotate; + if (undo) + b = (4 - b) & 3; + /* 0 - flip; 1-3, rotate. */ + if (b) + pcb_element_rotate90(PCB->Data, pt->element, bbcx, bbcy, b); + else { + pcb_coord_t y = pt->element->VBox.Y1; + pcb_element_mirror(PCB->Data, pt->element, 0); + /* mirroring moves the element. move it back. */ + pcb_element_move(PCB->Data, pt->element, 0, y - pt->element->VBox.Y1); + } + return; + } + case EXCHANGE: + { + /* first exchange positions */ + pcb_coord_t x1 = pt->element->VBox.X1; + pcb_coord_t y1 = pt->element->VBox.Y1; + pcb_coord_t x2 = pt->other->BoundingBox.X1; + pcb_coord_t y2 = pt->other->BoundingBox.Y1; + pcb_element_move(PCB->Data, pt->element, x2 - x1, y2 - y1); + pcb_element_move(PCB->Data, pt->other, x1 - x2, y1 - y2); + /* then flip both elements if they are on opposite sides */ + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pt->element) != PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, pt->other)) { + PerturbationType mypt; + mypt.element = pt->element; + mypt.which = ROTATE; + mypt.rotate = 0; /* flip */ + doPerturb(&mypt, undo); + mypt.element = pt->other; + doPerturb(&mypt, undo); + } + /* done */ + return; + } + default: + assert(0); + } +} + +/* --------------------------------------------------------------------------- + * Auto-place selected components. + */ +pcb_bool AutoPlaceSelected(void) +{ + pcb_netlist_t *Nets; + vtptr_t Selected; + PerturbationType pt; + double C0, T0; + pcb_bool changed = pcb_false; + + vtptr_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 (vtptr_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 * vtptr_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(); + } + vtptr_uninit(&Selected); + return (changed); +} Index: tags/1.2.3/src_plugins/autoplace/autoplace.h =================================================================== --- tags/1.2.3/src_plugins/autoplace/autoplace.h (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/autoplace.h (revision 8969) @@ -0,0 +1,40 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + +/* prototypes for autoplace routines */ + +#ifndef PCB_AUTOPLACE_H +#define PCB_AUTOPLACE_H + +#include "global_typedefs.h" + +pcb_bool AutoPlaceSelected(void); + +#endif Index: tags/1.2.3/src_plugins/autoplace/autoplace.pup =================================================================== --- tags/1.2.3/src_plugins/autoplace/autoplace.pup (nonexistent) +++ tags/1.2.3/src_plugins/autoplace/autoplace.pup (revision 8969) @@ -0,0 +1,6 @@ +$class feature +$short auto place components +$long Automatically place elements. +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/autoroute/Makefile =================================================================== --- tags/1.2.3/src_plugins/autoroute/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_autoroute + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/autoroute/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/autoroute/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/autoroute/action.c =================================================================== --- tags/1.2.3/src_plugins/autoroute/action.c (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/action.c (revision 8969) @@ -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.3/src_plugins/autoroute/autoroute.c =================================================================== --- tags/1.2.3/src_plugins/autoroute/autoroute.c (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/autoroute.c (revision 8969) @@ -0,0 +1,4743 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "vtptr.h" +#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. + */ +/* --------------------------------------------------------------------------- + * some local types + */ + +/* 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; +}; + + +/* --------------------------------------------------------------------------- + * some local prototypes + */ +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 + +/* --------------------------------------------------------------------------- + * some local identifiers + */ +/* 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(vtptr_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 **)vtptr_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(vtptr_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 **) vtptr_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(vtptr_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 **) vtptr_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(vtptr_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 **) vtptr_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(vtptr_t layergroupboxes[], pcb_cardinal_t layer, pcb_polygon_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(vtptr_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(vtptr_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; + vtptr_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].On) { + 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++) { + vtptr_init(&layergroupboxes[i]); + PCB_COPPER_GROUP_LOOP(PCB->Data, i); + { + if (linelist_length(&layer->Line) || arclist_length(&layer->Arc)) + 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->ptr2); + if (connection->type == PCB_TYPE_LINE) { + pcb_line_t *line = (pcb_line_t *) connection->ptr2; + + /* 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->type) { + case PCB_TYPE_PAD: + rb = AddPad(layergroupboxes, (pcb_element_t *) connection->ptr1, (pcb_pad_t *) connection->ptr2, rd->styles[j]); + break; + case PCB_TYPE_PIN: + rb = AddPin(layergroupboxes, (pcb_pin_t *) connection->ptr2, pcb_false, rd->styles[j]); + break; + case PCB_TYPE_VIA: + rb = AddPin(layergroupboxes, (pcb_pin_t *) connection->ptr2, pcb_true, rd->styles[j]); + break; + case PCB_TYPE_POLYGON: + rb = + AddPolygon(layergroupboxes, + pcb_layer_id(PCB->Data, (pcb_layer_t *) connection->ptr1), + (struct pcb_polygon_s *) connection->ptr2, rd->styles[j]); + break; + } + 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, vtptr_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 < vtptr_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++) + vtptr_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) + DrawVia(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) + DrawLine(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]); + EraseLine(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) { + EraseVia(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->On) + break; + } + assert(layer && layer->On); /*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(type, pin->Element ? pin->Element : pin, pin, 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(PCB_TYPE_RATLINE, line, line, line); + PCB_FLAG_ASSIGN(PCB_FLAG_SELECTED, pcb_true, line); + DrawRat(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.3/src_plugins/autoroute/autoroute.h =================================================================== --- tags/1.2.3/src_plugins/autoroute/autoroute.h (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/autoroute.h (revision 8969) @@ -0,0 +1,43 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* prototypes for autoroute routines + */ + +#ifndef PCB_AUTOROUTE_H +#define PCB_AUTOROUTE_H + +#include "config.h" +#include "board.h" + +pcb_bool AutoRoute(pcb_bool); + +#endif Index: tags/1.2.3/src_plugins/autoroute/autoroute.pup =================================================================== --- tags/1.2.3/src_plugins/autoroute/autoroute.pup (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/autoroute.pup (revision 8969) @@ -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.3/src_plugins/autoroute/mtspace.c =================================================================== --- tags/1.2.3/src_plugins/autoroute/mtspace.c (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/mtspace.c (revision 8969) @@ -0,0 +1,508 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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. */ + +/* --------------------------------------------------------------------------- + * some local types + */ + +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.3/src_plugins/autoroute/mtspace.h =================================================================== --- tags/1.2.3/src_plugins/autoroute/mtspace.h (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/mtspace.h (revision 8969) @@ -0,0 +1,77 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* prototypes for "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.3/src_plugins/autoroute/vector.c =================================================================== --- tags/1.2.3/src_plugins/autoroute/vector.c (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/vector.c (revision 8969) @@ -0,0 +1,214 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* --------------------------------------------------------------------------- + * some local prototypes + */ + +/* --------------------------------------------------------------------------- + * some local types + */ +struct vector_struct { + vector_element_t *element; + int size, max; +}; + +/* --------------------------------------------------------------------------- + * some local identifiers + */ + +/* --------------------------------------------------------------------------- + * functions. + */ + +/* 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.3/src_plugins/autoroute/vector.h =================================================================== --- tags/1.2.3/src_plugins/autoroute/vector.h (nonexistent) +++ tags/1.2.3/src_plugins/autoroute/vector.h (revision 8969) @@ -0,0 +1,76 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Contact addresses for paper mail and Email: + * harry eaton, 6697 Buttonhole Ct, Columbia, MD 21044 USA + * haceaton@aplcomm.jhuapl.edu + * + */ + + +/* prototypes for vector routines. + */ + +#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.3/src_plugins/boardflip/Makefile =================================================================== --- tags/1.2.3/src_plugins/boardflip/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/boardflip/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_boardflip + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/boardflip/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/boardflip/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/boardflip/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/boardflip/boardflip.c =================================================================== --- tags/1.2.3/src_plugins/boardflip/boardflip.c (nonexistent) +++ tags/1.2.3/src_plugins/boardflip/boardflip.c (revision 8969) @@ -0,0 +1,276 @@ +/*! + * \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 elem_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 (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; + PCB_ELEMENT_LOOP(data); + { + XFLIP(element->MarkX); + YFLIP(element->MarkY); + if ((elem_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 (elem_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 ((elem_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.3/src_plugins/boardflip/boardflip.h =================================================================== --- tags/1.2.3/src_plugins/boardflip/boardflip.h (nonexistent) +++ tags/1.2.3/src_plugins/boardflip/boardflip.h (revision 8969) @@ -0,0 +1,5 @@ +#include "data.h" +#include "unit.h" + +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 elem_swap_sides); + Index: tags/1.2.3/src_plugins/boardflip/boardflip.pup =================================================================== --- tags/1.2.3/src_plugins/boardflip/boardflip.pup (nonexistent) +++ tags/1.2.3/src_plugins/boardflip/boardflip.pup (revision 8969) @@ -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.3/src_plugins/dbus/HACKING =================================================================== --- tags/1.2.3/src_plugins/dbus/HACKING (nonexistent) +++ tags/1.2.3/src_plugins/dbus/HACKING (revision 8969) @@ -0,0 +1,5 @@ +Needs scconfig detection. Does anyone use dbus? + +Makefile: + EXTRA_DIST += dbus.xml + DISTCLEAN_FILES += dbus-introspect.h \ Index: tags/1.2.3/src_plugins/dbus/Makefile =================================================================== --- tags/1.2.3/src_plugins/dbus/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/dbus/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_dbus + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/dbus/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/dbus/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/dbus/Plug.tmpasm (revision 8969) @@ -0,0 +1,30 @@ +put /local/pcb/mod {dbus} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/dbus/dbus.o $(PLUGDIR)/dbus/dbus-pcbmain.o @] + +switch /local/pcb/dbus/controls + case {disable} + # create the introspect header even if disabled so make dep works + put /local/tmp { $(PLUGDIR)/dbus/dbus-introspect.tmp } + append /local/pcb/DEPDEPS [@ $(PLUGDIR)/dbus/dbus-introspect.h @] + end; + default + put /local/pcb/mod/CFLAGS /target/libs/sul/dbus/cflags + put /local/pcb/mod/LDFLAGS /target/libs/sul/dbus/ldflags + + put /local/tmp { $(PLUGDIR)/dbus/dbus-introspect.tmp } + end +end + +append /local/pcb/RULES [@ +# DBUS xml embedded +$(PLUGDIR)/dbus/dbus-introspect.h: $(PLUGDIR)/dbus/dbus.xml $(CQUOTE) + $(CQUOTE) -n pcb_dbus_introspect_xml < $(PLUGDIR)/dbus/dbus.xml > $(PLUGDIR)/dbus/dbus-introspect.h +@] + +put /local/pcb/mod/CLEANFILES { $(PLUGDIR)/dbus/dbus-introspect.h } + +switch /local/pcb/dbus/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.3/src_plugins/dbus/dbus-pcbmain.c =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus-pcbmain.c (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus-pcbmain.c (revision 8969) @@ -0,0 +1,310 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* dbus-pcbmain.c PCB HID main loop integration + * + * Adapted from dbus-gmain.c from dbus-glib bindings: + * Copyright (C) 2002, 2003 CodeFactory AB + * Copyright (C) 2005 Red Hat, Inc. + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 + * + */ + + +#include "config.h" + +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include +#include +#include "dbus-pcbmain.h" +#include "hid.h" + +typedef struct _IOWatchHandler IOWatchHandler; +typedef struct _TimeoutHandler TimeoutHandler; + +struct _IOWatchHandler { + DBusWatch *dbus_watch; + pcb_hidval_t pcb_watch; +}; + +struct _TimeoutHandler { + DBusTimeout *dbus_timeout; + pcb_hidval_t pcb_timer; + int interval; +}; + + +static void block_hook_cb(pcb_hidval_t data) +{ + DBusConnection *connection = (DBusConnection *) data.ptr; + if (dbus_connection_get_dispatch_status(connection) != DBUS_DISPATCH_DATA_REMAINS) + return; + + /* TODO: IS THIS NEEDED? */ + /* dbus_connection_ref (connection); */ + + /* Only dispatch once - we don't want to starve other mainloop users */ + dbus_connection_dispatch(connection); + + /* dbus_connection_unref (connection); */ + return; +} + +static void io_watch_handler_dbus_freed(void *data) +{ + IOWatchHandler *handler; + handler = (IOWatchHandler *) data; + + /* Remove the watch registered with the HID */ + if (pcb_gui != NULL) + pcb_gui->unwatch_file(handler->pcb_watch); + free(handler); +} + + +void io_watch_handler_cb(pcb_hidval_t pcb_watch, int fd, unsigned int condition, pcb_hidval_t data) +{ + IOWatchHandler *handler; + unsigned int dbus_condition = 0; + + handler = (IOWatchHandler *) data.ptr; + + /* TODO: IS THIS NEEDED? */ + /* if (connection) + dbus_connection_ref (connection); */ + + if (condition & PCB_WATCH_READABLE) + dbus_condition |= DBUS_WATCH_READABLE; + if (condition & PCB_WATCH_WRITABLE) + dbus_condition |= DBUS_WATCH_WRITABLE; + if (condition & PCB_WATCH_ERROR) + dbus_condition |= DBUS_WATCH_ERROR; + if (condition & PCB_WATCH_HANGUP) + dbus_condition |= DBUS_WATCH_HANGUP; + + /* We don't touch the handler after this, because DBus + * may have disabled the watch and thus killed the handler + */ + dbus_watch_handle(handler->dbus_watch, dbus_condition); + handler = NULL; + + /*if (connection) + dbus_connection_unref (connection); */ + + return; +} + + +static void timeout_handler_dbus_freed(void *data) +{ + TimeoutHandler *handler; + handler = (TimeoutHandler *) data; + + /* Remove the timeout registered with the HID */ + pcb_gui->stop_timer(handler->pcb_timer); + free(handler); +} + + +void timeout_handler_cb(pcb_hidval_t data) +{ + TimeoutHandler *handler; + handler = (TimeoutHandler *) data.ptr; + + /* Re-add the timeout, as PCB will remove the current one + Do this before calling to dbus, incase DBus removes the timeout. + We can't touch handler after libdbus has been run for this reason. */ + handler->pcb_timer = pcb_gui->add_timer(timeout_handler_cb, handler->interval, data); + + dbus_timeout_handle(handler->dbus_timeout); +} + + +static dbus_bool_t watch_add(DBusWatch * dbus_watch, void *data) +{ + IOWatchHandler *handler; + int fd; + unsigned int pcb_condition; + unsigned int dbus_flags; + pcb_hidval_t temp; + + /* We won't create a watch until it becomes enabled. */ + if (!dbus_watch_get_enabled(dbus_watch)) + return TRUE; + + dbus_flags = dbus_watch_get_flags(dbus_watch); + + pcb_condition = PCB_WATCH_ERROR | PCB_WATCH_HANGUP; + if (dbus_flags & DBUS_WATCH_READABLE) + pcb_condition |= PCB_WATCH_READABLE; + if (dbus_flags & DBUS_WATCH_WRITABLE) + pcb_condition |= PCB_WATCH_READABLE; + +#if HAVE_DBUS_WATCH_GET_UNIX_FD + fd = dbus_watch_get_unix_fd(dbus_watch); +#else + fd = dbus_watch_get_fd(dbus_watch); +#endif + + handler = (IOWatchHandler *) malloc(sizeof(IOWatchHandler)); + temp.ptr = (void *) handler; + handler->dbus_watch = dbus_watch; + handler->pcb_watch = pcb_gui->watch_file(fd, pcb_condition, io_watch_handler_cb, temp); + + dbus_watch_set_data(dbus_watch, handler, io_watch_handler_dbus_freed); + return TRUE; +} + +static void watch_remove(DBusWatch * dbus_watch, void *data) +{ + /* Free the associated data. Its destroy callback removes the watch */ + dbus_watch_set_data(dbus_watch, NULL, NULL); +} + +static void watch_toggled(DBusWatch * dbus_watch, void *data) +{ + /* Simply add/remove the watch completely */ + if (dbus_watch_get_enabled(dbus_watch)) + watch_add(dbus_watch, data); + else + watch_remove(dbus_watch, data); +} + + +static dbus_bool_t timeout_add(DBusTimeout * timeout, void *data) +{ + TimeoutHandler *handler; + pcb_hidval_t temp; + + /* We can't create a timeout without a GUI */ + if (pcb_gui == NULL) + return TRUE; + + /* We won't create a timeout until it becomes enabled. */ + if (!dbus_timeout_get_enabled(timeout)) + return TRUE; + + /*FIXME: Need to store the interval, as PCB requires us + to manually re-add the timer each time it expires. + This is non-ideal, and hopefully can be changed? */ + + handler = (TimeoutHandler *) malloc(sizeof(TimeoutHandler)); + temp.ptr = (void *) handler; + handler->dbus_timeout = timeout; + handler->interval = dbus_timeout_get_interval(timeout); + handler->pcb_timer = pcb_gui->add_timer(timeout_handler_cb, handler->interval, temp); + + dbus_timeout_set_data(timeout, handler, timeout_handler_dbus_freed); + return TRUE; +} + +static void timeout_remove(DBusTimeout * timeout, void *data) +{ + /* Free the associated data. Its destroy callback removes the timer */ + dbus_timeout_set_data(timeout, NULL, NULL); +} + +static void timeout_toggled(DBusTimeout * timeout, void *data) +{ + /* Simply add/remove the timeout completely */ + if (dbus_timeout_get_enabled(timeout)) + timeout_add(timeout, data); + else + timeout_remove(timeout, data); +} + +void dispatch_status_changed(DBusConnection * conn, DBusDispatchStatus new_status, void *data) +{ + /* TODO: Can use this eventually to add one-shot idle work-functions to dispatch + remaining IO. It could possibly replace the block_hook polling mechanism. + (We could use a one-shot block_book to dispatch the work though.) + + *** NO DISPATCHING TO BE DONE INSIDE THIS FUNCTION *** */ +} + +/* END INTERNALS */ + + +/** + * Sets the watch and timeout functions of a #DBusConnection + * to integrate the connection with the GUI HID's main loop. + * + * @param connection the connection + */ +void pcb_dbus_connection_setup_with_mainloop(DBusConnection * connection) +{ + /* ConnectionSetup *cs; */ + pcb_hidval_t temp; + + /* FIXME we never free the slot, so its refcount just keeps growing, + * which is kind of broken. + */ + /* dbus_connection_allocate_data_slot (&connection_slot); + if (connection_slot < 0) + goto nomem; */ + +#if 0 + cs = connection_setup_new(connection); + + if (!dbus_connection_set_data(connection, connection_slot, cs, (DBusFreeFunction) connection_setup_free)) + goto nomem; +#endif + + if (!dbus_connection_set_watch_functions(connection, watch_add, watch_remove, watch_toggled, NULL, NULL)) +/* cs, NULL))*/ + goto nomem; + + if (!dbus_connection_set_timeout_functions(connection, timeout_add, timeout_remove, timeout_toggled, NULL, NULL)) +/* cs, NULL))*/ + goto nomem; + + dbus_connection_set_dispatch_status_function(connection, dispatch_status_changed, NULL, NULL); +/* cs, NULL);*/ + + /* Register a new mainloop hook to mop up any unfinished IO. */ + temp.ptr = (void *) connection; + pcb_gui->add_block_hook(block_hook_cb, temp); + + return; +nomem: + fprintf(stderr, "Not enough memory to set up DBusConnection for use with PCB\n"); +} + +void pcb_dbus_connection_finish_with_mainloop(DBusConnection * connection) +{ + /*ConnectionSetup *cs; + + cs = dbus_connection_get_data (connection, connection_slot ); + + Replace the stored data with NULL, thus freeing the old data + DBus will call the function connection_setup_free() which we registered earlier + dbus_connection_set_data (connection, connection_slot, NULL, NULL ); + + dbus_connection_free_data_slot( &connection_slot ); */ + + if (!dbus_connection_set_watch_functions(connection, NULL, NULL, NULL, NULL, NULL)) + goto nomem; + + if (!dbus_connection_set_timeout_functions(connection, NULL, NULL, NULL, NULL, NULL)) + goto nomem; + + dbus_connection_set_dispatch_status_function(connection, NULL, NULL, NULL); + return; +nomem: + fprintf(stderr, "Not enough memory when cleaning up DBusConnection mainloop integration\n"); + +} Index: tags/1.2.3/src_plugins/dbus/dbus-pcbmain.h =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus-pcbmain.h (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus-pcbmain.h (revision 8969) @@ -0,0 +1,29 @@ +/* + * PCB, an interactive printed circuit board editor + * D-Bus IPC logic + * Copyright (C) 2006 University of Cambridge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 + */ +#ifndef PCB_DBUS_PCBMAIN_H +#define PCB_DBUS_PCBMAIN_H + +#define DBUS_API_SUBJECT_TO_CHANGE +#include + +void pcb_dbus_connection_setup_with_mainloop(DBusConnection * connection); +void pcb_dbus_connection_finish_with_mainloop(DBusConnection * connection); + +#endif /* !PCB_DBUS_PCBMAIN_H */ Index: tags/1.2.3/src_plugins/dbus/dbus.c =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus.c (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus.c (revision 8969) @@ -0,0 +1,391 @@ +/* + * PCB, an interactive printed circuit board editor + * D-Bus IPC logic + * Copyright (C) 2006 University of Cambridge + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You 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 + */ + +/* + * D-Bus code originally derrived from example-service.c in the dbus-glib bindings + */ + +#warning scconfig TODO: detect this in scconfig: +/* Define to 1 if you have the `dbus_watch_get_unix_fd' function. */ +/* #undef HAVE_DBUS_WATCH_GET_UNIX_FD */ + + + +#define DBUS_API_SUBJECT_TO_CHANGE +#include +#include + +#include "dbus-pcbmain.h" +#include "dbus-introspect.h" +#include "board.h" +#include "config.h" +#include "data.h" +#include "plugins.h" +#include "hid_actions.h" +#include "event.h" +#include "compat_misc.h" +#include "hid.h" + +/* For lrealpath */ +#include "compat_lrealpath.h" + + +#define PCB_DBUS_CANONICAL_NAME "org.seul.geda.pcb" +#define PCB_DBUS_OBJECT_PATH "/org/seul/geda/pcb" +#define PCB_DBUS_INTERFACE "org.seul.geda.pcb" +#define PCB_DBUS_ACTIONS_INTERFACE "org.seul.geda.pcb.actions" + +const char *dbus_cookie = "dbus plugin"; + +static DBusConnection *pcb_dbus_conn; + +static DBusHandlerResult handle_get_filename(DBusConnection * connection, DBusMessage * message, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter; + DBusHandlerResult result; + char *filename; + + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + /* TODO: Should check the message signature matches what we expect? */ + + reply = dbus_message_new_method_return(message); + if (reply == NULL) { + fprintf(stderr, "pcb_dbus: Couldn't create reply message\n"); + return result; + } + dbus_message_iter_init_append(reply, &iter); + + if (PCB->Filename) + filename = pcb_lrealpath(PCB->Filename); + else + filename = NULL; + + if (filename == NULL) { +#ifdef DEBUG + fprintf(stderr, "pcb_dbus: DEBUG: Couldn't get working filename, assuming none\n"); +#endif + filename = pcb_strdup(""); + if (filename == NULL) { + fprintf(stderr, "pcb_dbus: Couldn't pcb_strdup( \"\" ) for the filename\n"); + goto out; + } + } + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &filename)) { + fprintf(stderr, "pcb_dbus: Couldn't append return filename string to message reply, Out Of Memory!\n"); + free(filename); + goto out; + } + free(filename); + if (!dbus_connection_send(connection, reply, NULL)) { + fprintf(stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n"); + goto out; + } + result = DBUS_HANDLER_RESULT_HANDLED; + +out: + dbus_message_unref(reply); + return result; +} + + +static DBusHandlerResult handle_exec_action(DBusConnection * connection, DBusMessage * message, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter; + DBusHandlerResult result; + DBusError err; + dbus_uint32_t retval; + char *action_name; + char **argv; + int argc; +#ifdef DEBUG + int i; +#endif + + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + /* TODO: Should check the message signature matches what we expect? */ + + /* initialise the error struct */ + dbus_error_init(&err); + + /* DON'T FREE action_name, as it belongs to DBUS, + * DO FREE argv, using dbus_free_string_array() + */ + argv = NULL; + if (!dbus_message_get_args(message, + &err, + DBUS_TYPE_STRING, &action_name, + DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &argv, &argc, DBUS_TYPE_INVALID)) { + fprintf(stderr, "Failed to read method arguments\n"); + if (argv) + dbus_free_string_array(argv); + return result; + } + +#ifdef DEBUG + fprintf(stderr, "pcb_dbus: DEBUG: Executing action: %s(", action_name); + if (argc > 0) + fprintf(stderr, " \"%s\"", argv[0]); + for (i = 1; i < argc; i++) + fprintf(stderr, ", \"%s\"", argv[i]); + fprintf(stderr, " )\n"); +#endif + + /* TODO: Proper return value from actions */ + pcb_hid_actionv(action_name, argc, (const char**)argv); + retval = 0; + + dbus_free_string_array(argv); + + reply = dbus_message_new_method_return(message); + if (reply == NULL) { + fprintf(stderr, "pcb_dbus: Couldn't create reply message\n"); + return result; + } + dbus_message_iter_init_append(reply, &iter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &retval)) { + fprintf(stderr, "pcb_dbus: Couldn't sent message, Out Of Memory!\n"); + goto out; + } + + if (!dbus_connection_send(connection, reply, NULL)) { + fprintf(stderr, "pcb_dbus: Couldn't send message, Out Of Memory!\n"); + goto out; + } + + result = DBUS_HANDLER_RESULT_HANDLED; +out: + dbus_message_unref(reply); + return result; +} + + +static DBusHandlerResult handle_introspect(DBusConnection * connection, DBusMessage * message, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter; + DBusHandlerResult result; + + result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + reply = dbus_message_new_method_return(message); + if (reply == NULL) { + fprintf(stderr, "pcb_dbus: Couldn't create reply message\n"); + return result; + } + dbus_message_iter_init_append(reply, &iter); + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &pcb_dbus_introspect_xml)) { + fprintf(stderr, "pcb_dbus: Couldn't add introspect XML to message return\n"); + goto out; + } + if (!dbus_connection_send(pcb_dbus_conn, reply, NULL)) { + fprintf(stderr, "pcb_dbus: Couldn't queue reply message for sending\n"); + goto out; + } + result = DBUS_HANDLER_RESULT_HANDLED; +out: + dbus_message_unref(reply); + return result; +} + +static void unregister_dbus_handler(DBusConnection * connection, void *data) +{ +} + + +static DBusHandlerResult handle_dbus_message(DBusConnection * connection, DBusMessage * message, void *data) +{ + int msg_type; + msg_type = dbus_message_get_type(message); + + switch (msg_type) { + case DBUS_MESSAGE_TYPE_METHOD_CALL: + { + const char *method_name; + const char *interface_name; + + method_name = dbus_message_get_member(message); + if (method_name == NULL) { + fprintf(stderr, "pcb_dbus: Method had no name specified\n"); + break; + } + + interface_name = dbus_message_get_interface(message); + if (interface_name == NULL) { + fprintf(stderr, "pcb_dbus: Method had no interface specified\n"); + break; + } + + if (strcmp(interface_name, PCB_DBUS_INTERFACE) == 0) { + if (strcmp(method_name, "GetFilename") == 0) { + return handle_get_filename(connection, message, data); + } + fprintf(stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", interface_name, method_name); + break; + } + else if (strcmp(interface_name, PCB_DBUS_ACTIONS_INTERFACE) == 0) { + if (strcmp(method_name, "ExecAction") == 0) { + return handle_exec_action(connection, message, data); + } + fprintf(stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", interface_name, method_name); + break; + } + else if (strcmp(interface_name, DBUS_INTERFACE_INTROSPECTABLE) == 0) { + if (strcmp(method_name, "Introspect") == 0) { + return handle_introspect(connection, message, data); + } + fprintf(stderr, "pcb_dbus: Interface '%s' has no method '%s'\n", interface_name, method_name); + break; + } + else { + fprintf(stderr, "pcb_dbus: Interface '%s' was not recognised\n", interface_name); + break; + } + } + break; + + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + fprintf(stderr, "pcb_dbus: DBUG: Method return message\n"); + /* WON'T ACTUALLY BE ANY UNLESS WE MAKE AN ASYNCRONOUS CALL? */ + break; + + case DBUS_MESSAGE_TYPE_ERROR: + fprintf(stderr, "pcb_dbus: DEBUG: Error message\n"); + /* HOPE NOT! */ + break; + + case DBUS_MESSAGE_TYPE_SIGNAL: + fprintf(stderr, "pcb_dbus: DEBUG: Signal message\n"); + /* NONE AT PRESENT */ + break; + + default: + fprintf(stderr, "pcb_dbus: DEBUG: Message type wasn't one we know about!\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + + +static void pcb_dbus_setup(void) +{ + DBusError err; + int ret; + const DBusObjectPathVTable object_vtable = { + unregister_dbus_handler, + handle_dbus_message, + NULL, NULL, NULL, NULL + }; + + /* Initialise the error variable */ + dbus_error_init(&err); + + /* Connect to the bus */ + pcb_dbus_conn = dbus_bus_get_private(DBUS_BUS_SESSION, &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "pcb_dbus: DBus connection Error (%s)\n", err.message); + dbus_error_free(&err); + } + if (pcb_dbus_conn == NULL) + return; + + /* Request the canonical name for PCB on the bus */ + ret = dbus_bus_request_name(pcb_dbus_conn, PCB_DBUS_CANONICAL_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &err); + if (dbus_error_is_set(&err)) { + fprintf(stderr, "pcb_dbus: DBus name error (%s)\n", err.message); + dbus_error_free(&err); + } + if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER && ret != DBUS_REQUEST_NAME_REPLY_IN_QUEUE) { + fprintf(stderr, "pcb_dbus: Couldn't gain ownership or queued ownership of the canonical DBus name\n"); + return; + } + + if (!dbus_connection_register_object_path(pcb_dbus_conn, PCB_DBUS_OBJECT_PATH, &object_vtable, NULL /* void * user_data */ + )) { + fprintf(stderr, "pcb_dbus: Couldn't register DBUS handler for %s\n", PCB_DBUS_OBJECT_PATH); + return; + } + + /* Setup intergration with the pcb mainloop */ + pcb_dbus_connection_setup_with_mainloop(pcb_dbus_conn); + +/* dbus_error_free(&err); */ + return; +} + + +static void pcb_dbus_finish(void) +{ + DBusError err; + + /* Initialise the error variable */ + dbus_error_init(&err); + + /* TODO: Could emit a "goodbye" signal here? */ + + dbus_connection_flush(pcb_dbus_conn); + + dbus_connection_unregister_object_path(pcb_dbus_conn, PCB_DBUS_OBJECT_PATH); + + dbus_bus_release_name(pcb_dbus_conn, PCB_DBUS_CANONICAL_NAME, &err); + + dbus_error_free(&err); + + pcb_dbus_connection_finish_with_mainloop(pcb_dbus_conn); + + dbus_connection_close(pcb_dbus_conn); + dbus_connection_unref(pcb_dbus_conn); + + /* Call DBus shutdown. This doesn't work with shared connections, + only private ones (like we took out earlier). + If any future module / plugin to PCB wants to use DBus too, + we must remove this call. DBus will get shut-down when the app exits. */ + dbus_shutdown(); +} + +static void dbus_gui_init(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + + /* this can not be done from init, before the gui starts, as it needs + to register fd watches in the GUI. Also won't play well together with GUI + switches... */ + + pcb_dbus_setup(); +} + +int pplg_check_ver_dbus(int ver_needed) { return 0; } + +void pplg_uninit_dbus(void) +{ + pcb_dbus_finish(); + pcb_event_unbind_allcookie(dbus_cookie); +/* pcb_hid_remove_actions_by_cookie(dbus_cookie);*/ +} + +#include "dolists.h" +int pplg_init_dbus(void) +{ +/* PCB_REGISTER_ACTIONS(debug_action_list, dbus_cookie)*/ + pcb_event_bind(PCB_EVENT_GUI_INIT, dbus_gui_init, NULL, dbus_cookie); + return 0; +} Index: tags/1.2.3/src_plugins/dbus/dbus.mk =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus.mk (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus.mk (revision 8969) @@ -0,0 +1,11 @@ +append /local/pcb/OBJS {dbus-pcbmain.o dbus.o} + +append /local/pcb/RULES [@ +# dbus +dbus-introspect.h : dbus.xml Makefile + echo '/* AUTOMATICALLY GENERATED FROM dbus.xml DO NOT EDIT */' > $@.tmp + echo "static const char *pcb_dbus_introspect_xml =" > $@.tmp + sed 's/\\/\\\\/g; s/"/\\"/g; s/^/"/; s/$$/"/' < dbus.xml >> $@.tmp + echo ";" >> $@.tmp + mv $@.tmp $@ +@] Index: tags/1.2.3/src_plugins/dbus/dbus.pup =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus.pup (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus.pup (revision 8969) @@ -0,0 +1,7 @@ +$class feature +$short DBUS interface +$long Remote control PCB using DBUS. +$state WIP +$lstate needs to install the xml? +default disable +autoload 1 Index: tags/1.2.3/src_plugins/dbus/dbus.xml =================================================================== --- tags/1.2.3/src_plugins/dbus/dbus.xml (nonexistent) +++ tags/1.2.3/src_plugins/dbus/dbus.xml (revision 8969) @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + Index: tags/1.2.3/src_plugins/diag/Makefile =================================================================== --- tags/1.2.3/src_plugins/diag/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/diag/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_diag + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/diag/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/diag/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/diag/Plug.tmpasm (revision 8969) @@ -0,0 +1,8 @@ +put /local/pcb/mod {diag} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/diag/diag.o $(PLUGDIR)/diag/diag_conf.o @] + +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.3/src_plugins/diag/diag.c =================================================================== --- tags/1.2.3/src_plugins/diag/diag.c (nonexistent) +++ tags/1.2.3/src_plugins/diag/diag.c (revision 8969) @@ -0,0 +1,275 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" +#include "board.h" +#include "data.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" + +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_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(layer_id)); + } + + /* query by logical layer: any bottom copper */ + used = pcb_layer_list(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 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; +} + + +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} + +}; + +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); +} + +#include "dolists.h" +int pplg_init_diag(void) +{ + PCB_REGISTER_ACTIONS(diag_action_list, diag_cookie) + return 0; +} Index: tags/1.2.3/src_plugins/diag/diag.pup =================================================================== --- tags/1.2.3/src_plugins/diag/diag.pup (nonexistent) +++ tags/1.2.3/src_plugins/diag/diag.pup (revision 8969) @@ -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.3/src_plugins/diag/diag_conf.c =================================================================== --- tags/1.2.3/src_plugins/diag/diag_conf.c (nonexistent) +++ tags/1.2.3/src_plugins/diag/diag_conf.c (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src_plugins/diag/diag_conf.h =================================================================== --- tags/1.2.3/src_plugins/diag/diag_conf.h (nonexistent) +++ tags/1.2.3/src_plugins/diag/diag_conf.h (revision 8969) @@ -0,0 +1,4 @@ + +/* 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); Index: tags/1.2.3/src_plugins/distalign/Makefile =================================================================== --- tags/1.2.3/src_plugins/distalign/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/distalign/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distalign + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/distalign/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/distalign/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/distalign/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/distalign/distalign.c =================================================================== --- tags/1.2.3/src_plugins/distalign/distalign.c (nonexistent) +++ tags/1.2.3/src_plugins/distalign/distalign.c (revision 8969) @@ -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(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.3/src_plugins/distalign/distalign.pup =================================================================== --- tags/1.2.3/src_plugins/distalign/distalign.pup (nonexistent) +++ tags/1.2.3/src_plugins/distalign/distalign.pup (revision 8969) @@ -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.3/src_plugins/distaligntext/Makefile =================================================================== --- tags/1.2.3/src_plugins/distaligntext/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/distaligntext/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_distaligntext + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/distaligntext/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/distaligntext/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/distaligntext/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/distaligntext/distaligntext.c =================================================================== --- tags/1.2.3/src_plugins/distaligntext/distaligntext.c (nonexistent) +++ tags/1.2.3/src_plugins/distaligntext/distaligntext.c (revision 8969) @@ -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.3/src_plugins/distaligntext/distaligntext.pup =================================================================== --- tags/1.2.3/src_plugins/distaligntext/distaligntext.pup (nonexistent) +++ tags/1.2.3/src_plugins/distaligntext/distaligntext.pup (revision 8969) @@ -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.3/src_plugins/djopt/Makefile =================================================================== --- tags/1.2.3/src_plugins/djopt/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/djopt/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_djopt + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/djopt/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/djopt/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/djopt/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/djopt/djopt.c =================================================================== --- tags/1.2.3/src_plugins/djopt/djopt.c (nonexistent) +++ tags/1.2.3/src_plugins/djopt/djopt.c (revision 8969) @@ -0,0 +1,2716 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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; +} + +#if 0 +/* Not used */ +static corner_s *common_corner(line_s * l1, line_s * l2) +{ + if (l1->s == l2->s || l1->s == l2->e) + return l1->s; + if (l1->e == l2->s || l1->e == l2->e) + return l1->e; + dj_abort("common_corner: no common corner found\n"); + return NULL; +} +#endif + +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)); + 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); +} + +#if 0 +/* Not used */ +static int c_orth_to(corner_s * c, line_s * l, int o) +{ + int i, o2; + int rv = 0; + for (i = 0; i < c->n_lines; i++) { + if (c->lines[i] == l) + continue; + o2 = line_orient(c->lines[i], c); + if (ORIENT(o) == ORIENT(o2) || o2 == DIAGONAL) + return 0; + rv++; + } + return rv; +} +#endif + +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; +} + +#if 0 +/* Not used */ +static int corner_layer(corner_s * c) +{ + if (c->pin || c->via) + return -1; + if (c->n_lines < 1) + return -1; + return c->lines[0]->layer; +} +#endif + +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 +/* Not used */ +static void dump_all() +{ + corner_s *c; + line_s *l; + for (c = corners; c; c = c->next) { + if (DELETED(c)) + continue; + printf("%p corner %d,%d layer %d net %d\n", (void *) c, c->x, c->y, c->layer, c->net); + } + for (l = lines; l; l = l->next) { + if (DELETED(l)) + continue; + printf("%p line %p to %p layer %d\n", (void *) l, (void *) (l->s), (void *) (l->e), l->layer); + } +} +#endif + +#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)); + /* 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.3/src_plugins/djopt/djopt.h =================================================================== --- tags/1.2.3/src_plugins/djopt/djopt.h (nonexistent) +++ tags/1.2.3/src_plugins/djopt/djopt.h (revision 8969) @@ -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., 675 Mass Ave, Cambridge, MA 02139, 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.3/src_plugins/djopt/djopt.pup =================================================================== --- tags/1.2.3/src_plugins/djopt/djopt.pup (nonexistent) +++ tags/1.2.3/src_plugins/djopt/djopt.pup (revision 8969) @@ -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.3/src_plugins/djopt/djopt_conf.h =================================================================== --- tags/1.2.3/src_plugins/djopt/djopt_conf.h (nonexistent) +++ tags/1.2.3/src_plugins/djopt/djopt_conf.h (revision 8969) @@ -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.3/src_plugins/draw_csect/Makefile =================================================================== --- tags/1.2.3/src_plugins/draw_csect/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/draw_csect/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_csect + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/draw_csect/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/draw_csect/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/draw_csect/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/draw_csect/draw_csect.c =================================================================== --- tags/1.2.3/src_plugins/draw_csect/draw_csect.c (nonexistent) +++ tags/1.2.3/src_plugins/draw_csect/draw_csect.c (revision 8969) @@ -0,0 +1,843 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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(); + DrawTextLowLevel(&t, 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(); + DrawTextLowLevel(&t, th); + 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); + DrawTextLowLevel(&t, 1000000); + } + + pcb_gui->set_color(gc, fgcolor); + DrawTextLowLevel(&t, 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); + _draw_line(&l); +} + +/* 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); + _draw_line(&l); +} + + +/* 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 char layer_valid[PCB_MAX_LAYER]; +static char group_valid[PCB_MAX_LAYERGRP]; + +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 reset_layer_coords(void) +{ + memset(layer_valid, 0, sizeof(layer_valid)); + memset(group_valid, 0, sizeof(group_valid)); +} + +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_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_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_layer_group_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) +{ + pcb_layergrp_id_t gid; + int ystart = 10, x, y, last_copper_step = 5, has_outline = 0; + + 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_layer_group_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) { + has_outline = 1; + 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->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->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 */ + if (has_outline) { + pcb_gui->set_color(gc, COLOR_OUTLINE); + dline(0, ystart, 0, y+10, 1); + dtext_bg(gc, 1, y+7, 200, 0, "outline", COLOR_BG, COLOR_ANNOT); + } + + y+=7; + 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); + 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_layer_order(cx); + } + else if (drag_gid >= 0) { + pcb_layer_group_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_layer_group_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_layer_group_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(gactive, "New Layer"); + 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, "%d", 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_layer_group_t *g; + if (l->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 + 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_layer_group_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->grp != gid) + printf(" *** broken layer-to-group cross reference: %ld\n", l->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.3/src_plugins/draw_csect/draw_csect.pup =================================================================== --- tags/1.2.3/src_plugins/draw_csect/draw_csect.pup (nonexistent) +++ tags/1.2.3/src_plugins/draw_csect/draw_csect.pup (revision 8969) @@ -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.3/src_plugins/draw_fab/Makefile =================================================================== --- tags/1.2.3/src_plugins/draw_fab/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/draw_fab/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fab + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/draw_fab/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/draw_fab/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/draw_fab/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/draw_fab/draw_fab.c =================================================================== --- tags/1.2.3/src_plugins/draw_fab/draw_fab.c (nonexistent) +++ tags/1.2.3/src_plugins/draw_fab/draw_fab.c (revision 8969) @@ -0,0 +1,317 @@ +/* + * 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., 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 + * + */ + +/* printing routines */ +#include "config.h" + +#include + +#include "board.h" +#include "build_run.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_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; + DrawTextLowLevel(&t, 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) +{ + DrillInfoTypePtr AllDrills; + int i, n, yoff, total_drills = 0, ds = 0, found; + char utcTime[64]; + AllDrills = GetDrillInfo(PCB->Data); + RoundDrillInfo(AllDrills, PCB_MIL_TO_COORD(1)); + 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++) + drill_sym(gc, PCB_FLAG_TEST(PCB_FLAG_HOLE, drill->Pin[i]) ? unplated_sym : plated_sym, drill->Pin[i]->X, drill->Pin[i]->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); + text_at(gc, PCB_MIL_TO_COORD(450), yoff, PCB_MIL_TO_COORD(2), "%0.3f", PCB_COORD_TO_INCH(drill->DrillSize) + 0.0004); + if (plated_sym != -1 && unplated_sym != -1) + text_at(gc, PCB_MIL_TO_COORD(450), yoff + TEXT_LINE, PCB_MIL_TO_COORD(2), "%0.3f", PCB_COORD_TO_INCH(drill->DrillSize) + 0.0004); + 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"); + text_at(gc, PCB_MIL_TO_COORD(410), yoff, PCB_MIL_TO_COORD(9), "Diam. (Inch)"); + 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) { + const char *fmt = "%c UTC"; + time_t currenttime = time(NULL); + strftime(utcTime, sizeof utcTime, fmt, gmtime(¤ttime)); + } + 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) && (linelist_length(&l->Line) || arclist_length(&l->Arc))) { + 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); + { + DrawTextLowLevel(text, 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.3/src_plugins/draw_fab/draw_fab.pup =================================================================== --- tags/1.2.3/src_plugins/draw_fab/draw_fab.pup (nonexistent) +++ tags/1.2.3/src_plugins/draw_fab/draw_fab.pup (revision 8969) @@ -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.3/src_plugins/draw_fab/draw_fab_conf.h =================================================================== --- tags/1.2.3/src_plugins/draw_fab/draw_fab_conf.h (nonexistent) +++ tags/1.2.3/src_plugins/draw_fab/draw_fab_conf.h (revision 8969) @@ -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.3/src_plugins/draw_fontsel/Makefile =================================================================== --- tags/1.2.3/src_plugins/draw_fontsel/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/draw_fontsel/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_draw_fontsel + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/draw_fontsel/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/draw_fontsel/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/draw_fontsel/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/draw_fontsel/draw_fontsel.c =================================================================== --- tags/1.2.3/src_plugins/draw_fontsel/draw_fontsel.c (nonexistent) +++ tags/1.2.3/src_plugins/draw_fontsel/draw_fontsel.c (revision 8969) @@ -0,0 +1,251 @@ +/* + * 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., 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 + * + */ + +/* 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(); + DrawTextLowLevel(&t, 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); + _draw_line(&l); +} + +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_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; + + /* 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_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.3/src_plugins/draw_fontsel/draw_fontsel.pup =================================================================== --- tags/1.2.3/src_plugins/draw_fontsel/draw_fontsel.pup (nonexistent) +++ tags/1.2.3/src_plugins/draw_fontsel/draw_fontsel.pup (revision 8969) @@ -0,0 +1,5 @@ +$class feature +$short font selection GUI +$long Draw the font selector GUI +$state WIP +default disable Index: tags/1.2.3/src_plugins/export_bboard/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_bboard/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_bboard/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bboard + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_bboard/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_bboard/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_bboard/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_bboard/bboard.c =================================================================== --- tags/1.2.3/src_plugins/export_bboard/bboard.c (nonexistent) +++ tags/1.2.3/src_plugins/export_bboard/bboard.c (revision 8969) @@ -0,0 +1,605 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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->Attributes), "BBoard::LayerColor")) != NULL) { + if (clr[0] == '#') { + if (sscanf(&(clr[1]), "%02x%02x%02x", &r, &g, &b) == 3) + goto ok; + } + } + + if (layer->Color && (layer->Color[0] == '#')) { + if (sscanf(&(layer->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 (linelist_length(&layer->Line) > 0) + 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.3/src_plugins/export_bboard/export_bboard.pup =================================================================== --- tags/1.2.3/src_plugins/export_bboard/export_bboard.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_bboard/export_bboard.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short breadboard pcb_exporter +$long Export breadboard +$state WIP +default disable-all +autoload 1 Index: tags/1.2.3/src_plugins/export_bom/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_bom/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_bom/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_bom + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_bom/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_bom/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_bom/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_bom/bom.c =================================================================== --- tags/1.2.3/src_plugins/export_bom/bom.c (nonexistent) +++ tags/1.2.3/src_plugins/export_bom/bom.c (revision 8969) @@ -0,0 +1,331 @@ +#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 "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]; + time_t currenttime; + FILE *fp; + BomList *bom = NULL; + + /* Create a portable timestamp. */ + currenttime = time(NULL); + { + /* avoid gcc complaints */ + const char *fmt = "%c UTC"; + strftime(utcTime, sizeof(utcTime), fmt, gmtime(¤ttime)); + } + + + 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 = 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 foo.pcb [bom_options]\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) +{ +} + +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.3/src_plugins/export_bom/export_bom.pup =================================================================== --- tags/1.2.3/src_plugins/export_bom/export_bom.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_bom/export_bom.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short bom pcb_exporter +$long Export bom (Bill of Materials) +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_dsn/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_dsn/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_dsn/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dsn + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_dsn/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_dsn/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_dsn/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_dsn/dsn.c =================================================================== --- tags/1.2.3/src_plugins/export_dsn/dsn.c (nonexistent) +++ tags/1.2.3/src_plugins/export_dsn/dsn.c (revision 8969) @@ -0,0 +1,605 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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 "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].On) { + 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->On) + 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].On) { + 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(PCB, pcb_layer_id(PCB->Data, 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_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 print_library(FILE * fp) +{ + GList *pads = NULL, *iter; /* contain unique pad names */ + gchar *padstack; + 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); + { + 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); + } + + if (!g_list_find_custom(pads, padstack, (GCompareFunc) strcmp)) + pads = g_list_append(pads, padstack); + else + g_free(padstack); + } + PCB_END_LOOP; + + PCB_PAD_LOOP(element); + { + 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); + } + if (!g_list_find_custom(pads, padstack, (GCompareFunc) strcmp)) + pads = g_list_append(pads, padstack); + else + g_free(padstack); + } + 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"); + if (!g_list_find_custom(pads, padstack, (GCompareFunc) strcmp)) + pads = g_list_append(pads, padstack); + else + g_free(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"); + pcb_fprintf(fp, " )\n"); + g_list_foreach(pads, (GFunc) g_free, NULL); + g_list_free(pads); +} + +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 = 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 \"gEDA 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.3/src_plugins/export_dsn/export_dsn.pup =================================================================== --- tags/1.2.3/src_plugins/export_dsn/export_dsn.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_dsn/export_dsn.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short specctra .dsn pcb_exporter +$long Export specctra .dsn files +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_dxf/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_dxf/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_dxf/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_dxf + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_dxf/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_dxf/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_dxf/Plug.tmpasm (revision 8969) @@ -0,0 +1,8 @@ +put /local/pcb/mod {export_dxf} +put /local/pcb/mod/OBJS [@ $(PLUGDIR)/export_dxf/dxf.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 Index: tags/1.2.3/src_plugins/export_dxf/README =================================================================== --- tags/1.2.3/src_plugins/export_dxf/README (nonexistent) +++ tags/1.2.3/src_plugins/export_dxf/README (revision 8969) @@ -0,0 +1,47 @@ +The pcb DXF HID is a DXF exporter for pcb. + +The pcb DXF HID exports the loaded pcb layout to a series of DXF files, +typically one file for every layer, a DXF file for inserting elements by +means of "XREFS" (in AutoCAD jargon also known as eXternal REFerenced +drawings), and DXF files for plated and non-plated holes. + +These external referenced drawings can be 3D models of elements (ACIS), +including DDE/OLE attributes of any other application that is supported +by both AutoCAD (or any alternative software that supports these +features) and the (Microsoft) Operating System of your choice. + +The parameters for the DXF exporter are: + +--dxffile + +This is the basename of the generated files. +Layer-, top and bottom mask-, top and bottom paste, and drill-filenames +are based upon this string. + +--metric +Tick for mm, default is mil. + +--layer-color-BYBLOCK +Tick for layer color is BYBLOCK, default layer color is BYLAYER. + +--xrefs +Tick for generating an eXternal REFerence file, default is none. + +--xreffile +This string should contain the pathname of the location where your XREF +drawing files exist. + +--verbose +Tick if you want to see a full report on stderr of what entities are +written to the files, default is silent. + +--export-all-layers +Tick if you want to export all layers, default is to not export empty +layers. + +------------------------------------------------------------------------- + COPYRIGHT + +The pcb DXF HID is covered by the GNU General Public License. +See the individual files for the exact copyright notices. + Index: tags/1.2.3/src_plugins/export_dxf/dxf.c =================================================================== --- tags/1.2.3/src_plugins/export_dxf/dxf.c (nonexistent) +++ tags/1.2.3/src_plugins/export_dxf/dxf.c (revision 8969) @@ -0,0 +1,5969 @@ +/* + * 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 + * + */ + +/*! + * \file dxf.c + * + * \author Copyright (C) 2007 .. 2011 by Bert Timmerman + * for DXF relevant code.\n + * + * \brief This file contains the DXF HID (Human Interface Device) exporter to + * generate a DXF file containing Xref's of components and a series of DXF + * files, one for every pcb layer. + * + *
+ * Drawing eXchange Format (DXF)\n + * DXF is a defacto industry standard for the exchange of drawing files + * between various Computer Aided Drafting programs.\n + * DXF is designed by Autodesk(TM).\n + * For more details see http://www.autodesk.com . + *
+ *

Warning.

\n + * Some notes about Coordinate systems:\n + *
    + *
  • PCB follows a "left handed" Cartesian Coordinate System.\n + * Positive X is right, positive Y is down.\n + * Angles are increasing counter clockwise (CCW) in degrees, with 0 degrees being left + * (negative X-axis) and 90 degrees being down (positive Y-axis).\n + *
  • AutoCAD DXF follows a "right handed" Cartesian Coordinate system.\n + * Positive X is right, positive Y is up.\n + * Angles are counter clockwise (CCW) in degrees, with 0 being right + * (positive X) and 90 being up (positive Y).\n + *
  • Autocad coordinates are either in mil (default) or in mm (see checkbox + * in the DXF HID dialog).\n + *
  • Lookup Wikipedia with keywords "Cartesian Coordinates" if you want more + * information on this subject.\n + *
+ * Filled polygons are drawn with a hatch entity.\n + * Elliptic arcs are drawn with an ellipse entity.\n + * Successful importing the generated dxf files with these entities + * requires AutoCAD version R14 or higher, or any other mechanical CAD + * program with the same level of compatibility with regard to the DXF + * format.\n + *
+ *

+ * Please send remarks, bugs, improvements, relevant opinions to + * bert.timmerman@xs4all.nl or to the geda-dev mailing list. \n + * Donations to speed up the development of the gEDA suite best go to + * www.gedaconsulting.com. \n + *

  • Have fun ;-) + * + *
    + *

    + *

    The DXF HID function treeview.

    \n + * The following function hierarchy, with the status of the functions in + * between [], exists: + *
      + *
    • dxf_get_export_options [stable] + *
    • dxf_do_export [stable] + *
        + *
      • dxf_get_export_options [stable] + *
      • dxf_export_xref_file [exp] + *
          + *
        • dxf_write_comment [stable] + *
        • dxf_write_header [stable] + *
            + *
          • dxf_write_header_metric_new [stable] + *
          • dxf_write_header_imperial_new [todo] + *
          + *
        • dxf_write_block_record [todo] + *
        • dxf_write_block [stable] + *
        • dxf_write_endsection [stable] + *
        • dxf_write_section [stable] + *
        • dxf_insert [stable] + *
        • dxf_write_eof [stable] + *
        + *
      • dxf_maybe_close_file [exp] + *
          + *
        • dxf_write_tail [todo] + *
        • dxf_write_tail_metric_new [todo] + *
        • dxf_write_tail_imperial_new [todo] + *
        • dxf_write_eof [stable] + *
        + *
      + *
    • dxf_parse_arguments [stable] + *
    • dxf_set_layer [exp] + *
        + *
      • dxf_maybe_close_file [stable] + *
      • dxf_write_header [stable] + *
          + *
        • dxf_write_header_metric_new [stable] + *
        • dxf_write_header_imperial_new [todo] + *
        + *
      • dxf_write_block_record [todo] + *
      • dxf_write_block [stable] + *
      • dxf_write_endsection [stable] + *
      • dxf_write_section [stable] + *
      + *
    • dxf_make_gc [stable] + *
    • dxf_destroy_gc [stable] + *
    • dxf_use_mask [stable] + *
    • dxf_set_color [stable] + *
    • dxf_set_line_cap [stable] + *
    • dxf_set_line_width [stable] + *
    • dxf_draw_line [exp] + *
        + *
      • dxf_write_polyline [exp] + *
      • dxf_write_vertex [stable] + *
      • dxf_write_endseq [stable] + *
      + *
    • dxf_draw_arc [exp] + *
        + *
      • dxf_write_ellipse [exp] + *
      + *
    • dxf_draw_rect [exp] + *
        + *
      • dxf_write_polyline [exp] + *
      • dxf_write_vertex [stable] + *
      • dxf_write_endseq [stable] + *
      + *
    • dxf_fill_circle [exp] + *
        + *
      • dxf_write_circle [exp] + *
      + *
    • dxf_fill_polygon [exp] + *
        + *
      • dxf_write_hatch [stable] + *
      • dxf_write_hatch_boundary_path_polyline [stable] + *
      • dxf_write_hatch_boundary_path_polyline_vertex [stable] + *
      + *
    • dxf_fill_rect [stable] + *
        + *
      • dxf_write_solid [stable] + *
      + *
    • dxf_calibrate [stable] + *
    • dxf_set_crosshair [stable] + *
    + *
    + * Notes:\n + * [todo] denotes a function not yet implemented.\n + * [exp] denotes a function not yet fully implemented.\n + * [stable] denotes a function fully implemented.\n + *
    + * \n\n + * Include files + */ + + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "math_helper.h" +#include "macro.h" +#include "board.h" +#include "config.h" +#include "data.h" +#include "error.h" +#include "draw.h" +#include "hid_draw_helpers.h" +#include "pcb-printf.h" +#include "compat_misc.h" +#include "layer.h" +#include "hid_attrib.h" +#include "hid_flags.h" +#include "hid_helper.h" +#include "hid.h" +#include "hid_init.h" +#include "plugins.h" +#include "obj_pinvia.h" + +/*! + * \brief List with string data. + */ +typedef struct _StringList { + char *str; + /*!< String value. */ + struct _StringList *next; + /*!< Pointer to next item. */ +} StringList; + + +/*! + * \brief List with pcb element header data. + */ +typedef struct _DxfList { + char *descr; + /*!< description of pcb element. */ + char *value; + /*!< value of pcb element. */ + int num; + /*!< amount of elements per unique pcb element. */ + StringList *refdes; + /*!< list of reference designators (refdes's) of pcb elements. */ + struct _DxfList *next; + /*!< pointer to next (unique) element header data. */ +} DxfList; + + +#define NOSHAPE 0 +#define SHP_ROUND 1 /* shaped like a circle */ +#define SHP_OCTAGON 2 /* shape like an octagon */ +#define SHP_SQUARE 3 /* shaped like a square */ +#define SHP_ROUNDCLEAR 4 /* round clearance in negatives */ +#define SHP_SQUARECLEAR 5 /* square clearance in negatives */ +#define SHP_THERMAL 6 /* negative thermal relief */ + + +/* + * Function prototypes. + */ +static void dxf_beep(void); +static void dxf_calibrate(double xval, double yval); +static char *dxf_clean_string(char *in); +static void dxf_destroy_gc(pcb_hid_gc_t gc); +static void dxf_do_export(pcb_hid_attr_val_t * options); +static void dxf_draw_arc(pcb_hid_gc_t gc, int cx, int cy, int width, int height, int start_angle, int delta_angle); +static void dxf_draw_line(pcb_hid_gc_t gc, int x1, int y1, int x2, int y2); +static void dxf_draw_rect(pcb_hid_gc_t gc, int x1, int y1, int x2, int y2); +static int dxf_drill_sort(const void *va, const void *vb); +static int dxf_export_xref_file(void); +static void dxf_fill_circle(pcb_hid_gc_t gc, int cx, int cy, int radius); +static void dxf_fill_polygon(pcb_hid_gc_t gc, int n_coords, int *x, int *y); +static void dxf_fill_rect(pcb_hid_gc_t gc, int x1, int y1, int x2, int y2); +static pcb_hid_attribute_t *dxf_get_export_options(int *n); +static pcb_layergrp_id_t dxf_group_for_layer(int l); +static DxfList *dxf_insert(char *refdes, char *descr, char *value, DxfList * dxf); +static int dxf_layer_sort(const void *va, const void *vb); +static pcb_hid_gc_t dxf_make_gc(void); +static void dxf_maybe_close_file(); +static void dxf_parse_arguments(int *argc, char ***argv); +static void dxf_progress(int dxf_so_far, int dxf_total, const char *dxf_message); +static void dxf_set_color(pcb_hid_gc_t gc, const char *name); +static void dxf_set_crosshair(int x, int y); +static void dxf_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style); +static void dxf_set_line_width(pcb_hid_gc_t gc, int width); +static void dxf_show_item(void *item); +static StringList *dxf_string_insert(char *str, StringList * list); +static void dxf_use_gc(pcb_hid_gc_t gc, int radius); +static void dxf_use_mask(pcb_mask_op_t use_it); +static void dxf_write_block(FILE * fp, int id_code, char *xref_name, + char *block_name, char *linetype, char *layer, double x0, + double y0, double z0, double thickness, int color, int paperspace, int block_type); +static void dxf_write_circle(FILE * fp, int id_code, char *linetype, + char *layer, double x0, double y0, double z0, double extr_x0, + double extr_y0, double extr_z0, double thickness, double radius, int color, int paperspace); +static void dxf_write_comment(FILE * fp, char *comment_string); +static void dxf_write_ellipse(FILE * fp, int id_code, char *linetype, + char *layer, double x0, double y0, double z0, double x1, + double y1, double z1, double extr_x0, double extr_y0, + double extr_z0, double thickness, double ratio, + double start_angle, double end_angle, int color, int paperspace); +static void dxf_write_endsection(FILE * fp); +static void dxf_write_eof(FILE * fp); +static void dxf_write_hatch(FILE * fp, char *pattern_name, int id_code, + char *linetype, char *layer, double x0, double y0, double z0, + double extr_x0, double extr_y0, double extr_z0, double thickness, + double pattern_scale, double pixel_size, double pattern_angle, + int color, int paperspace, int solid_fill, int associative, + int style, int pattern_style, int pattern_double, + int pattern_def_lines, int boundary_paths, int seed_points, double *seed_x0, double *seed_y0); +static void dxf_write_hatch_boundary_path_polyline(FILE * fp, + int type_flag, int polyline_has_bulge, int polyline_is_closed, + int polyline_vertices); +static void dxf_write_hatch_boundary_path_polyline_vertex(FILE * fp, double x0, double y0, double bulge); +static void dxf_write_header(); +static void dxf_write_header_imperial_new(); +static void dxf_write_header_metric_new(); +static void dxf_write_insert(FILE * fp, int id_code, char *block_name, + char *linetype, char *layer, double x0, double y0, double z0, + double thickness, double rel_x_scale, double rel_y_scale, + double rel_z_scale, double column_spacing, double row_spacing, + double rot_angle, int color, int attribute_follows, int paperspace, int columns, int rows); +static void dxf_write_polyline(FILE * fp, int id_code, char *linetype, + char *layer, double x0, double y0, double z0, + double extr_x0, double extr_y0, double extr_z0, + double thickness, double start_width, double end_width, + int color, int vertices_follow, int paperspace, int flag, + int polygon_mesh_M_vertex_count, int polygon_mesh_N_vertex_count, + int smooth_M_surface_density, int smooth_N_surface_density, int surface_type); +static void dxf_write_section(FILE * fp, char *section_name); +static void dxf_write_solid(FILE * fp, int id_code, char *linetype, + char *layer, double x0, double y0, double z0, double x1, + double y1, double z1, double x2, double y2, double z2, + double x3, double y3, double z3, double thickness, int color, int paperspace); +static void dxf_write_table_block_record(FILE * fp); +static void dxf_write_vertex(FILE * fp, int id_code, char *linetype, + char *layer, double x0, double y0, double z0, double thickness, + double start_width, double end_width, double bulge, + double curve_fit_tangent_direction, int color, int paperspace, int flag); +static double dxf_xy_to_angle(double x, double y); + +/*! + * \brief Debugging on/off switch. + */ +#define DEBUG 0 + +/*! + * \brief Error handling of not yet implemented functions. + */ +#define CRASH fprintf(stderr, "DXF error: pcb called an unimplemented DXF-HID function %s.\n", __FUNCTION__); abort() + +/*! + * pcb dxf HID version string + */ +#define PCB_DXF_HID_VERSION "PCB DXF HID - Version 0.0.1 (2011-10-23)" + +/*! + * \brief Dxf X-coordinate (in mil). + */ +#define DXF_X(pcb,x) (x) + +/*! + * \brief Dxf Y-coordinate (in mil). + */ +#define DXF_Y(pcb,y) ((pcb)->MaxHeight-(y)) + +/*! + * \brief Dxf X offset (in mil). + */ +#define DXF_XOffset(pcb,x) (x) + +/*! + * \brief Dxf Y offset (in mil). + */ +#define DXF_YOffset(pcb,y) (-(y)) + +/*! + * \brief Round of value to the nearest multiple of 100. + */ +#define DXF_ROUND(x) ((int)(((x)+50)/100)*100) + +/*! + * \brief DXF color definition, entities with this color follow the color + * definition of the block in which it lives. + */ +#define DXF_COLOR_BYBLOCK 0 + +/*! + * \brief DXF color definition, pen number "1" in the virtual pen-plotter. + */ +#define DXF_COLOR_RED 1 + +/*! + * \brief DXF color definition, pen number "2" in the virtual pen-plotter. + */ +#define DXF_COLOR_YELLOW 2 + +/*! + * \brief DXF color definition, pen number "3" in the virtual pen-plotter. + */ +#define DXF_COLOR_GREEN 3 + +/*! + * \brief DXF color definition, pen number "4" in the virtual pen-plotter. + */ +#define DXF_COLOR_CYAN 4 + +/*! + * \brief DXF color definition, pen number "5" in the virtual pen-plotter. + */ +#define DXF_COLOR_BLUE 5 + +/*! + * \brief DXF color definition, pen number "6" in the virtual pen-plotter. + */ +#define DXF_COLOR_MAGENTA 6 + +/*! + * \brief DXF color definition, pen number "7" in the virtual pen-plotter. + */ +#define DXF_COLOR_WHITE 7 + +/*! + * \brief DXF color definition, pen number "8" in the virtual pen-plotter. + */ +#define DXF_COLOR_GREY 8 + +/*! + * \brief DXF color definition, color of the entity follows the color + * definition of the layer on which it lives. + */ +#define DXF_COLOR_BYLAYER 256 + +/*! + * \brief This is where our hardware is going to live, default value, can be + * ommitted in dxf output. + */ +#define DXF_MODELSPACE 0 + +/*! + * \brief This is where your annotation (papersheet templates, fab notes and + * such) should live, has to be included in DXF output for any entity to live + * on paperspace. + */ +#define DXF_PAPERSPACE 1 + +/*! + * \brief There is always a layer "0" defined, it's reasonably safe to + * assume that this is a valid layername. + */ +#define DXF_DEFAULT_LAYER "0" + +/*! + * \brief There is always a linetype "BYLAYER" defined, it's reasonably + * safe to assume that this is a valid linetype. + */ +#define DXF_DEFAULT_LINETYPE "BYLAYER" + +/*! + * \brief There is always a textstyle "STANDARD" defined, it's + * reasonably safe to assume that this is a valid text style. + */ +#define DXF_DEFAULT_TEXTSTYLE "STANDARD" + +/*! + * \brief Directory where 3D models of parts live. + * + * For now the dxf_xref_pathname is set to "parts", in AutoCAD one can + * configure default search directories for xrefs. + */ +#define DXF_DEFAULT_XREF_PATH_NAME "parts" + +/*! + * \brief Directory separator character (back slash). + * + * We target an Autodesk universe with all of it's quirks. + * + * \todo This has to be solved in a more elegant manner if we want to + * use DXF files for *nix based CAD software. + */ +#define DXF_DIR_SEPARATOR "\\" + +/*! + * \brief Default hatch pattern for pcb polygons. + * + * \todo For now the hatch pattern name is set to "SOLID".\n + * If pcb is ever to have thieving implemented, a hatch pattern name field + * has to be added to the graphic context. + */ +#define DXF_DEFAULT_HATCH_PATTERN_NAME "SOLID" + +/*! + * \brief File pointer for DXF layer files. + */ +static FILE *fp; + +/*! + * \brief File name of layer DXF files. + */ +static char *dxf_filename; + +/*! + * \brief File name suffix for layer files. + */ +static char *dxf_filesuffix; + +/*! + * \brief . + */ +static int dxf_finding_apertures = 0; + +/*! + * \brief Layer name. + */ +static char *dxf_layername = 0; + +/*! + * \brief Line count ??. + */ +static int lncount = 0; + +/*! + * \brief DXF file with xrefs needed. + */ +static int dxf_xrefs; + +/*! + * \brief File name of Xref (blocks) DXF file. + */ +static char *dxf_xref_filename; + +/*! + * \brief DXF file with output in mm (not mils). + */ +static int dxf_metric; + +/*! + * \brief DXF file with layer color BYBLOCK (or by layer number). + */ +static int dxf_color_is_byblock; + +/*! + * \brief DXF file with verbose output (to contain DXF comments). + */ +static int dxf_verbose; + +/*! + * \brief export all PCB layers to DXF files. + */ +static int dxf_export_all_layers; + +/*! + * \brief Every DXF entity has a unique identifier (per DXF file). + */ +static int dxf_id_code = 0; + +/*! + * \brief Record with all values of the DXF HID. + */ +static pcb_hid_t dxf_hid; + +/*! + * \brief Drill (hole) properties. + */ +typedef struct { + int diam; + /*!< drill diameter. */ + int x; + /*!< X-coordinate. */ + int y; + /*!< Y-coordinate. */ +} DxfPendingDrills; + +/*! + * \brief Layer is a mask. + */ +static int is_mask; + +/*! + * \brief Current mask. + */ +static int current_mask; + +/*! + * \brief Entity is a drill (hole). + */ +static int is_drill; + +static int was_drill; + +static int n_layerapps = 0; + +static int c_layerapps = 0; + +/*! + * \brief Pending drill (holes). + */ +DxfPendingDrills *dxf_pending_drills = 0; + +/*! + * \brief Number of pending drill (holes). + */ +int dxf_n_pending_drills = 0; + +/*! + * \brief Maximum number of pending drills (holes). + */ +int dxf_max_pending_drills = 0; + +/*! + * \brief Definition of graphic context for the dxf HID. + * + * This graphics context is an opaque pointer defined by the HID.\n + * GCs are HID-specific; attempts to use one HID's GC for a different + * HID will result in a fatal error.\n + * + * \todo In pcb the cap always extends beyond the coordinates + * given, by half the width of the line.\n + * With DXF polylines the cap is by default 0, and thus doesn't extend + * beyond the coordinates.\n + * A round cap could be implemented by drawing a donut (a series of + * polyline vertices) with an inner radius of zero at the start and + * endpoint of a line, this doesn't solve the problem for other aperture + * shapes, and is thus not yet implemented. + */ +typedef struct hid_gc_s { + pcb_cap_style_t cap; + /*!< end cap style. */ + int width; + /*!< width. */ + int color; + /*!< color. */ + int erase; + /*!< erase. */ + int drill; + /*!< drill. */ +} hid_gc_s; + +/*! + * \brief Definition of options the user can select in the DXF exporter + * dialog. + */ +static pcb_hid_attribute_t dxf_options[] = { +/* +%start-doc options "DXF Export" +@ftable @code +@item --dxffile +DXF output file prefix. Can include a path. +@end ftable +%end-doc +*/ + {"dxffile", "DXF layer filename base", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_dxffile 0 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --metric +Export DXF files in mm. Default is mil +@end ftable +%end-doc +*/ + {"metric", "export DXF files in mm", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_metric 1 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --layer-color-BYBLOCK +Export entities in color BYBLOCK. Default is BYLAYER. +@end ftable +%end-doc +*/ + {"layer-color-BYBLOCK", "export entities in color BYBLOCK", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_color_byblock 2 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --xrefs +Export a DXF file with XREFS. Default is no XREFS. +@end ftable +%end-doc +*/ + {"xrefs", "export a DXF file with xrefs", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_xrefs 3 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --xreffile +DXF Xrefs filename. Can include a path. +@end ftable +%end-doc +*/ + {"xreffile", "DXF Xrefs filename", + PCB_HATT_STRING, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_xreffile 4 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --verbose +Verbose output to stderr (comments). +@end ftable +%end-doc +*/ + {"be verbose", "verbose output to stderr (comments)", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_verbose 5 + +/* +%start-doc options "DXF Export" +@ftable @code +@item --export-all-layers +Export all layers. +@end ftable +%end-doc +*/ + {"export all layers", "export all layers", + PCB_HATT_BOOL, 0, 0, {0, 0, 0}, 0, 0}, +#define HA_export_all_layers 6 +}; + +#define NUM_OPTIONS (sizeof(dxf_options)/sizeof(dxf_options[0])) + +/*! + * \brief 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.\n + * PCB_HATT_LABEL just shows the default str_value.\n + * PCB_HATT_MIXED is a real_value followed by an enum, like 0.5in or 100mm. + */ +static pcb_hid_attr_val_t dxf_values[NUM_OPTIONS]; + +static int pagecount = 0; + +static int linewidth = -1; + +static int lastgroup = -1; + +static int lastcap = -1; + +static int lastcolor = -1; + +/*! + * \brief The last X coordinate. + */ +static int dxf_lastX; + +/*! + * \brief The last Y coordinate. + */ +static int dxf_lastY; + +/*! + * \brief Find a group for a given layer ??. + */ +static pcb_layergrp_id_t dxf_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; +} + +/*! + * \brief Sort layers ??. + */ +static int dxf_layer_sort(const void *va, const void *vb) { + int a; + int b; + int d; + + a = *(int *) va; + b = *(int *) vb; + d = dxf_group_for_layer(b) - dxf_group_for_layer(a); + if (d) + return d; + return b - a; +} + +/*! + * \brief Convert pcb x,y coordinates to an angle relative to (0.0, 0.0). + */ +static double dxf_xy_to_angle(double x, double y) { + double theta; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_xy_to_angle () function.\n", __FILE__, __LINE__); +#endif + if ((x > 0.0) && (y >= 0.0)) + theta = 180.0; + else if ((x <= 0.0) && (y > 0.0)) + theta = 90.0; + else if ((x < 0.0) && (y <= 0.0)) + theta = 0.0; + else if ((x >= 0.0) && (y < 0.0)) + theta = 270.0; + else { + theta = 0.0; + pcb_message(PCB_MSG_WARNING, "DXF: in dxf_xy_to_angle ():\n" + " unable to figure out angle of element\n" + " because the pin is at the centroid of the part.\n" + " This is a BUG!!!\n" " Setting to %g degrees\n", theta); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_xy_to_angle () function.\n", __FILE__, __LINE__); +#endif + return (theta); +} + + +/*! + * \brief Clean up a string. + * + * Copy over input string to output string with some character conversions.\n + * Go all the way to end of string to get the termination character. + */ +static char *dxf_clean_string(char *in) { + char *out; + int i; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_clean_string () function.\n", __FILE__, __LINE__); +#endif + if ((out = malloc((strlen(in) + 1) * sizeof(char))) == NULL) { + pcb_message(PCB_MSG_ERROR, "DXF: in dxf_clean_string (): malloc () failed.\n"); + exit(1); + } + for (i = 0; i <= strlen(in); i++) { + switch (in[i]) { + case '"': + out[i] = '\''; + break; + case ' ': + out[i] = '_'; + break; + default: + out[i] = in[i]; + break; + } + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_clean_string () function.\n", __FILE__, __LINE__); +#endif + return (out); +} + + +/*! + * \brief Insert the string to the list of strings. + */ +static StringList *dxf_string_insert(char *str, StringList * list) { + StringList *new; + StringList *cur; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_string_insert () function.\n", __FILE__, __LINE__); +#endif + if ((new = (StringList *) malloc(sizeof(StringList))) == NULL) { + pcb_message(PCB_MSG_ERROR, "DXF: in dxf_string_insert (): malloc () failed.\n"); + exit(1); + } + new->next = NULL; + new->str = pcb_strdup(str); + if (list == NULL) { + return (new); + } + cur = list; + while (cur->next != NULL) + cur = cur->next; + cur->next = new; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_string_insert () function.\n", __FILE__, __LINE__); +#endif + return (list); +} + + +/*! + * \brief Write DXF output to a file for a block entity. + * + * The BLOCKS section of the DXF file contains all the block + * definitions.\n + * It contains the entities that make up the blocks used in the drawing, + * including anonymous blocks generated by the HATCH command and by + * associative dimensioning.\n + * The format of the entities in this section is identical to those in the + * ENTITIES section.\n + * All entities in the BLOCKS section appear between block and endblk + * entities.\n + * Block and endblk entities appear only in the BLOCKS section.\n + * Block definitions are never nested (that is, no block or endblk entity ever + * appears within another block-endblk pair), although a block definition can + * contain an insert entity.\n + * \n + * External references are written in the DXF file as block definitions, + * except that they also include a string (group code 1) that specifies the + * path and file name of the external reference.\n + * \n + * The block table handle, along with any xdata and persistent reactors, + * appears in each block definition immediately following the BLOCK + * record, which contains all of the specific information that a block table + * record stores.\n + * \n + * The UCS in effect when a block definition is created becomes the WCS for + * all entities in the block definition.\n + * The new origin for these entities is shifted to match the base point + * defined for the block definition.\n + * All entity data is translated to fit this new WCS.\n + * \n + * *MODEL_SPACE and *PAPER_SPACE Block Definition.\n + * Now, there are always two extra, empty definitions in the BLOCKS section, + * titled *MODEL_SPACE and *PAPER_SPACE.\n + * These definitions manifest the new representation of model space and paper + * space as block definitions internally.\n + * The entities contained in these definitions still appear in the + * ENTITIES section for compatibility.\n + * \n + * Model Space and Paper Space Entity Segregation.\n + * The interleaving between model space and paper space will no longer occurs, + * because of internal organization.\n + * Instead, all paper space entities are output, followed by model space + * entities.\n + * The flag distinguishing them is the group code 67.\n + * + * \todo Add group code 102 stuff. + */ +static void dxf_write_block(FILE * fp, + /*!< file pointer to output file (or device). */ + int id_code, + /*!< group code = 5. */ + char *xref_name, + /*!< group code = 1. */ + char *block_name, + /*!< group code = 2 and 3. */ + char *linetype, + /*!< group code = 6\n + * optional, if omitted defaults to BYLAYER. */ + char *layer, + /*!< group code = 8. */ + double x0, + /*!< group code = 10\n + * base point. */ + double y0, + /*!< group code = 20\n + * base point. */ + double z0, + /*!< group code = 30\n + * base point. */ + double thickness, + /*!< group code = 39\n + * optional, if omitted defaults to 0.0. */ + int color, + /*!< group code = 62\n + * optional, if omitted defaults to BYLAYER. */ + int paperspace, + /*!< group code = 67\n + * optional, if omitted defaults to 0 (modelspace). */ + int block_type + /*!< group code = 70\n + * bit codes:\n + * 1 = this is an anonymous Block generated by hatching, + * associative dimensioning, other internal operations, or an + * application\n + * 2 = this Block has Attributes\n + * 4 = this Block is an external reference (Xref)\n + * 8 = not used\n + * 16 = this Block is externally dependent\n + * 32 = this is a resolved external reference, or dependent + * of an external reference\n + * 64 = this definition is referenced. */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_block () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("BLOCK"); + if (strcmp(block_name, "") == 0) { + if (dxf_verbose) { + fprintf(stderr, "DXF Warning: empty block name string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, "\t%s entity is discarded from output.\n", dxf_entity_name); + } + return; + } + if (strcmp(xref_name, "") == 0) { + if (dxf_verbose) { + fprintf(stderr, "DXF Warning: empty xref name string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, "\t%s entity is discarded from output.\n", dxf_entity_name); + } + return; + } + if (strcmp(layer, "") == 0) { + if (dxf_verbose) { + fprintf(stderr, "DXF Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, "\t%s entity is relocated to layer 0.\n", dxf_entity_name); + } + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + /* group code 102 stuff goes here */ + fprintf(fp, "100\nAcDbEntity\n"); + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, "100\nAcDbBlockBegin\n"); + fprintf(fp, " 2\n%s\n", block_name); + fprintf(fp, " 70\n%d\n", block_type); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, " 3\n%s\n", block_name); + if ((block_type && 4) || (block_type && 32)) { + fprintf(fp, " 1\n%s%s%s.dwg\n", xref_name, DXF_DIR_SEPARATOR, block_name); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } + /* now write an end block marker */ + fprintf(fp, " 0\nENDBLK\n"); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + /* group code 102 stuff goes here */ + fprintf(fp, "100\nAcDbBlockEnd\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_block () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a BLOCK_RECORD table. + * + * The DXF BLOCK_RECORD table is part of the TABLES section of + * the header that comes after the DIMSTYLE table and before the + * ENTITIES section.\n + * The BLOCK_RECORD table contains record definitions of all + * BLOCK entities, either regular BLOCK entities or external + * referenced BLOCK entities, the so calld XREFS.\n + * \todo Code it !! Make it happen !! + */ +static void dxf_write_table_block_record(FILE * fp + /*!< file pointer to output file (or device). */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_table_block_record () function.\n", __FILE__, __LINE__); +#endif + /*! \todo Add code. */ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_table_block_record () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a CIRCLE entity. + * + * \todo The CIRCLE entity has to be replaced by a POLYLINE + * entity with the correct line width (trace width). + * \todo The CIRCLE entity is to be used for (unplated) drill holes only. + * In the mechanical CAD program these circles (drill holes) can be extruded + * to the board thickness and subtracted from the extruded pcb outline. + */ +static void dxf_write_circle(FILE * fp, + /*!< file pointer to output file (or device). */ + int id_code, + /*!< group code = 5. */ + char *linetype, + /*!< group code = 6\n + * optional, defaults to BYLAYER. */ + char *layer, + /*!< group code = 8. */ + double x0, + /*!< group code = 10\n + * base point. */ + double y0, + /*!< group code = 20\n + * base point. */ + double z0, + /*!< group code = 30\n + * base point. */ + double extr_x0, + /*!< group code = 210\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_y0, + /*!< group code = 220\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_z0, + /*!< group code = 230\n + * extrusion direction\n + * optional, if ommited defaults to 1.0. */ + double thickness, + /*!< group code = 39\n + * optional, defaults to 0.0. */ + double radius, + /*!< group code = 40. */ + int color, + /*!< group code = 62\n + * optional, defaults to BYLAYER. */ + int paperspace + /*!< group code = 67\n + * optional, defaults to 0 (modelspace). */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_circle () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("CIRCLE"); + if (radius == 0.0) { + if (dxf_verbose) { + fprintf(stderr, "Error: radius value equals 0.0 for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + return; + } + } + if (strcmp(layer, "") == 0) { + layer = pcb_strdup(DXF_DEFAULT_LAYER); + if (dxf_verbose) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0", dxf_entity_name); + } + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + fprintf(fp, "100\nAcDbCircle\n"); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, " 210\n%f\n", extr_x0); + fprintf(fp, " 220\n%f\n", extr_y0); + fprintf(fp, " 230\n%f\n", extr_z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + fprintf(fp, " 40\n%f\n", radius); + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_circle () function.\n", __FILE__, __LINE__); +#endif + return; +} + + +/*! + * \brief Write DXF output for a comment string with line termination. + * + * The group code "999" indicates that the following line is a comment + * string.\n + * The AutoCAD command "DXFOUT" does not currently include such groups in a + * DXF output file.\n + * The AutoCAD command "DXFIN" honors them and ignores the comments.\n + * Thus, you can use the 999 group to include comments in a DXF file you've + * created. + */ +static void dxf_write_comment(FILE * fp, + /*!< file pointer to output file (or device). */ + char *comment_string + /*!< comment string. */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_comment () function.\n", __FILE__, __LINE__); +#endif + if (strcmp(comment_string, "") == 0) { + /* no use in writing an empty comment string to file */ + return; + } + fprintf(fp, "999\n%s\n", comment_string); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_comment () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for an ellipse entity. + * + * This entity requires AutoCAD version R14 or higher.\n + * The ellipse entity is currently used to draw arcs.\n + * Since the pcb file format allows for a height and a width value, it is thus + * possible to draw an elliptical arc. + * + * \todo The ellipse entity has to be replaced by a polyline with the correct + * line width (trace width). + * When we figured out how to draw a polyline (with vertices) for an arc + * (part of a circle) or an elliptical arc (part of an ellipse). + * This function will then become obsolete. + */ +static void dxf_write_ellipse(FILE * fp, + /*!< file pointer to output file (or device). */ + int id_code, + /*!< group code = 5. */ + char *linetype, + /*!< group code = 6\n + * optional, defaults to BYLAYER. */ + char *layer, + /*!< group code = 8. */ + double x0, + /*!< group code = 10\n + * base point. */ + double y0, + /*!< group code = 20\n + * base point. */ + double z0, + /*!< group code = 30\n + * base point. */ + double x1, + /*!< group code = 11\n + * endpoint of major axis, relative to the center (in WCS). */ + double y1, + /*!< group code = 21\n + * endpoint of major axis, relative to the center (in WCS). */ + double z1, + /*!< group code = 31\n + * endpoint of major axis, relative to the center (in WCS). */ + double extr_x0, + /*!< group code = 210\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_y0, + /*!< group code = 220\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_z0, + /*!< group code = 230\n + * extrusion direction\n + * optional, if ommited defaults to 1.0. */ + double thickness, + /*!< group code = 39\n + * optional, defaults to 0.0. */ + double ratio, + /*!< group code = 40\n + * ratio of minor axis to major axis. */ + double start_angle, + /*!< group code = 41\n + * start parameter (this value is 0.0 for a full ellipse). */ + double end_angle, + /*!< group code = 42\n + * end parameter (this value is 2*pi for a full ellipse). */ + int color, + /*!< group code = 62\n + * optional, defaults to BYLAYER. */ + int paperspace + /*!< group code = 67\n + * optional, defaults to 0 (modelspace). */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_ellipse () function.\n", __FILE__, __LINE__); +#endif + dxf_entity_name = pcb_strdup("ELLIPSE"); + if (ratio == 0.0) { + if (dxf_verbose) { + fprintf(stderr, "Error: ratio value equals 0.0 for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + } + return; + } + if (strcmp(layer, "") == 0) { + layer = pcb_strdup(DXF_DEFAULT_LAYER); + if (dxf_verbose) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0", dxf_entity_name); + } + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + fprintf(fp, "100\nAcDbEllipse\n"); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, " 11\n%f\n", x1); + fprintf(fp, " 21\n%f\n", y1); + fprintf(fp, " 31\n%f\n", z1); + fprintf(fp, " 210\n%f\n", extr_x0); + fprintf(fp, " 220\n%f\n", extr_y0); + fprintf(fp, " 230\n%f\n", extr_z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + fprintf(fp, " 40\n%f\n", ratio); + fprintf(fp, " 41\n%f\n", start_angle); + fprintf(fp, " 42\n%f\n", end_angle); + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_ellipse () function.\n", __FILE__, __LINE__); +#endif + return; +} + + +/*! + * \brief Write DXF output to a file for an end of section marker. + */ +static void dxf_write_endsection(FILE * fp + /*!< file pointer to output file (or device) */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_endsection () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, " 0\nENDSEC\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_endsection () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for an end of sequence marker. + * + * No fields.\n + * This marks the end of:\n + *
      + *
    • vertices (one or more "Vertex" entity) of a Polyline + *
    • attribute entities ("Attrib" entity) to an "Insert" entity that has + * Attributes (indicated by 66 group present and nonzero in Insert + * entity).\n + *
    + */ +static void dxf_write_endseq(FILE * fp + /*!< file pointer to output file (or device). */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_endseq () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, " 0\nENDSEQ\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_endseq () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write dxf output to a file for an EOF marker. + */ +static void dxf_write_eof(FILE * fp + /*!< file pointer to output file (or device). */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_eof () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, " 0\nEOF\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_eof () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a hatch entity. + * + * This entity requires AutoCAD version R14 or higher. + * + * \todo writing a hatch with a number of hatch_seed_points > 0 is creating a + * segmentation fault in the dxf hid (and thus pcb). + */ +static void dxf_write_hatch(FILE * fp, + /*!< file pointer to output file (or device). */ + char *pattern_name, + /*!< group code = 2. */ + int id_code, + /*!< group code = 5. */ + char *linetype, + /*!< group code = 6\n + * optional, defaults to BYLAYER. */ + char *layer, + /*!< group code = 8. */ + double x0, + /*!< group code = 10\n + * base point. */ + double y0, + /*!< group code = 20\n + * base point. */ + double z0, + /*!< group code = 30\n + * base point. */ + double extr_x0, + /*!< group code = 210\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_y0, + /*!< group code = 220\n + * extrusion direction\n + * optional, if ommited defaults to 0.0. */ + double extr_z0, + /*!< group code = 230\n + * extrusion direction\n + * optional, if ommited defaults to 1.0. */ + double thickness, + /*!< group code = 39\n + * optional, defaults to 0.0. */ + double pattern_scale, + /*!< group code 41\n + * pattern fill only. */ + double pixel_size, + /*!< group code 47. */ + double pattern_angle, + /*!< group code 52\n + * pattern fill only. */ + int color, + /*!< group code = 62\n + * optional, defaults to \c BYLAYER. */ + int paperspace, + /*!< group code = 67\n + * optional, defaults to 0 (modelspace). */ + int solid_fill, + /*!< group code = 70\n + * 0 = pattern fill\n + * 1 = solid fill. */ + int associative, + /*!< group code = 71\n + * 0 = non-associative\n + * 1 = associative. */ + int style, + /*!< group code = 75\n + * 0 = hatch "odd parity" area (Normal style)\n + * 1 = hatch outermost area only (Outer style)\n + * 2 = hatch through entire area (Ignore style). */ + int pattern_style, + /*!< group code = 76\n + * 0 = user defined\n + * 1 = predefined\n + * 2 = custom. */ + int pattern_double, + /*!< group code = 77\n + * pattern fill only\n + * 0 = not double\n + * 1 = double. */ + int pattern_def_lines, + /*!< group code = 78\n + * number of pattern definition lines. */ + int boundary_paths, + /*!< group code = 91\n + * number of boundary paths (loops). */ + int seed_points, + /*!< group code = 98\n + * number of seed points. */ + double *seed_x0, + /*!< group code = 10\n + * seed point X-value. */ + double *seed_y0 + /*!< group code = 20\n + * seed point Y-value. */ + ) { + char *dxf_entity_name; + int i; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_hatch () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("HATCH"); + if (strcmp(layer, "") == 0) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0", dxf_entity_name); + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + fprintf(fp, "100\nAcDbHatch\n"); + fprintf(fp, " 2\n%s\n", pattern_name); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, "210\n%f\n", extr_x0); + fprintf(fp, "220\n%f\n", extr_y0); + fprintf(fp, "230\n%f\n", extr_z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + if (!solid_fill) { + fprintf(fp, " 42\n%f\n", pattern_scale); + } + fprintf(fp, " 47\n%f\n", pixel_size); + if (!solid_fill) { + fprintf(fp, " 52\n%f\n", pattern_angle); + } + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } + fprintf(fp, " 70\n%d\n", solid_fill); + fprintf(fp, " 71\n%d\n", associative); + fprintf(fp, " 75\n%d\n", style); + if (!solid_fill) { + fprintf(fp, " 77\n%d\n", pattern_double); + } + fprintf(fp, " 78\n%d\n", pattern_def_lines); + fprintf(fp, " 98\n%d\n", seed_points); + for (i = 0; i < seed_points; i++) { + fprintf(fp, " 10\n%f\n", seed_x0[i]); + fprintf(fp, " 20\n%f\n", seed_y0[i]); + } + fprintf(fp, " 91\n%d\n", boundary_paths); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_hatch () function.\n", __FILE__, __LINE__); +#endif + return; +} + + +/*! + * \brief Write DXF output to a file for a hatch boundary path polyline. + * + * This entity requires AutoCAD version R14 or higher. + */ +static void dxf_write_hatch_boundary_path_polyline(FILE * fp, + /*!< file pointer to output file (or device). */ + int type_flag, + /*!< group code 92. */ + int polyline_has_bulge, + /*!< group code = 72\n + * polyline boundary data group only. */ + int polyline_is_closed, + /*!< group code = 73\n + * polyline boundary data group only. */ + int polyline_vertices + /*!< group code 93\n + * number of polyline vertices to follow. */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_hatch_boundary_path_polyline () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, " 92\n%d\n", type_flag); + fprintf(fp, " 72\n%d\n", polyline_has_bulge); + fprintf(fp, " 73\n%d\n", polyline_is_closed); + fprintf(fp, " 93\n%d\n", polyline_vertices); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_hatch_boundary_path_polyline () function.\n", __FILE__, __LINE__); +#endif + return; +} + + +/*! + * \brief Write DXF output to a file for a hatch boundary polyline entity. + * + * This entity requires AutoCAD version R14 or higher. + */ +static void dxf_write_hatch_boundary_path_polyline_vertex(FILE * fp, + /*!< file pointer to output file (or device). */ + double x0, + /*!< group code = 10\n + * X-value of vertex point. */ + double y0, + /*!< group code = 20\n + * Y-value of vertex point. */ + double bulge + /*!< group code 42\n + * bulge of polyline vertex\n + * optional, defaults to 0.0. */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_hatch_boundary_polyline_vertex () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + if (bulge != 0.0) { + fprintf(fp, " 42\n%f\n", bulge); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_hatch_boundary_polyline_vertex () function.\n", __FILE__, __LINE__); +#endif + return; +} + + +/*! + * \brief Write DXF output to a file for a imperial DXF header. + * + * Fall back for if no default imperial header template file exists in the + * pcb/src/hid/dxf/template directory.\n + * Write down a DXF header from scratch based on imperial values.\n + * Included sections and tables are:\n + *
      +*
    • HEADER section + *
    • CLASSES section + *
    • TABLES section + *
        + *
      • VPORT table + *
      • LTYPE table + *
      • LAYER table + *
      • STYLE table + *
      • VIEW table + *
      • UCS table + *
      • APPID table + *
      • DIMSTYLE table + *
      + *
    + */ +static void dxf_write_header_imperial_new() +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_header_imperial_new () function.\n", __FILE__, __LINE__); +#endif + /* write an imperial HEADER section */ + fprintf(fp, " 0\nSECTION\n"); + fprintf(fp, " 2\nHEADER\n"); /* Section name. */ + fprintf(fp, " 9\n$ACADVER\n 1\nAC1014\n"); /* AutoCAD drawing database version number. */ + fprintf(fp, " 9\n$ACADMAINTVER\n 70\n 0\n"); /* Maintenance version number. */ + fprintf(fp, " 9\n$DWGCODEPAGE\n 3\nANSI_1252\n"); /* Drawing code page. */ + fprintf(fp, " 9\n$INSBASE\n 10\n0.0\n 20\n0.0\n 30\n0.0\n"); /* Insertion base set by BASE command (in WCS). */ + fprintf(fp, " 9\n$EXTMIN\n0 10\n-0.012816\n 20\n-0.009063\n 30\n-0.001526\n"); /* X, Y, and Z drawing extents lower-left corner (in WCS). */ + fprintf(fp, " 9\n$EXTMAX\n 10\n88.01056\n 20\n35.022217\n 30\n0.0\n"); /* X, Y, and Z drawing extents upper-right corner (in WCS). */ + fprintf(fp, " 9\n$LIMMIN\n 10\n0.0\n 20\n0.0\n"); /* XY drawing limits lower-left corner (in WCS). */ + fprintf(fp, " 9\n$LIMMAX\n 10\n420.0\n 20\n297.0\n"); /* XY drawing limits upper-right corner (in WCS). */ + fprintf(fp, " 9\n$ORTHOMODE\n 70\n 0\n"); /* Ortho mode on if nonzero. */ + fprintf(fp, " 9\n$REGENMODE\n 70\n 1\n"); /* REGENAUTO mode on if nonzero. */ + fprintf(fp, " 9\n$FILLMODE\n 70\n 1\n"); /* Fill mode on if nonzero. */ + fprintf(fp, " 9\n$QTEXTMODE\n 70\n 0\n"); /* Quick text mode on if nonzero. */ + fprintf(fp, " 9\n$MIRRTEXT\n 70\n 1\n"); /* Mirror text if nonzero. */ + fprintf(fp, " 9\n$DRAGMODE\n 70\n 2\n"); /* 0 = off, 1 = on, 2 = auto. */ + fprintf(fp, " 9\n$LTSCALE\n 40\n1.0\n"); /* Global linetype scale. */ + fprintf(fp, " 9\n$OSMODE\n 70\n 125\n"); /* Running object snap modes. */ + fprintf(fp, " 9\n$ATTMODE\n 70\n 1\n"); /* Attribute visibility: 0 = none, 1 = normal, 2 = all. */ + fprintf(fp, " 9\n$TEXTSIZE\n 40\n0.1\n"); /* Default text height = 100 mil. */ + fprintf(fp, " 9\n$TRACEWID\n 40\n1.0\n"); /* Default trace width. */ + fprintf(fp, " 9\n$TEXTSTYLE\n 7\nSTANDARD\n"); /* Current text style name. */ + fprintf(fp, " 9\n$CLAYER\n 8\n0\n"); /* Current layer name. */ + fprintf(fp, " 9\n$CELTYPE\n 6\nBYLAYER\n"); /* Entity linetype name, or BYBLOCK or BYLAYER. */ + fprintf(fp, " 9\n$CECOLOR\n 62\n 256\n"); /* Current entity color number: 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$CELTSCALE\n 40\n1.0\n"); /* Current entity linetype scale. */ + fprintf(fp, " 9\n$DELOBJ\n 70\n 1\n"); /* Controls object deletion: 0=deleted, 1=retained. */ + fprintf(fp, " 9\n$DISPSILH\n 70\n 0\n"); /* Controls the display of silhouette curves of body objects in wire-frame mode: 0=Off, 1=On. */ + fprintf(fp, " 9\n$DIMSCALE\n 40\n1.0\n"); /* Overall dimensioning scale factor. */ + fprintf(fp, " 9\n$DIMASZ\n 40\n0.1\n"); /* Dimensioning arrow size = 100 mil. */ + fprintf(fp, " 9\n$DIMEXO\n 40\n0.01\n"); /* Extension line offset = 10 mil. */ + fprintf(fp, " 9\n$DIMDLI\n 40\n0.1\n"); /* Dimension line increment = 100 mil. */ + fprintf(fp, " 9\n$DIMRND\n 40\n0.0\n"); /* Rounding value for dimension distances. */ + fprintf(fp, " 9\n$DIMDLE\n 40\n0.0\n"); /* Dimension line extension */ + fprintf(fp, " 9\n$DIMEXE\n 40\n0.05\n"); /* Extension line extension = 50 mil. */ + fprintf(fp, " 9\n$DIMTP\n 40\n0.0\n"); /* Plus tolerance. */ + fprintf(fp, " 9\n$DIMTM\n 40\n0.0\n"); /* Minus tolerance. */ + fprintf(fp, " 9\n$DIMTXT\n 40\n0.1\n"); /* Dimensioning text height = 100 mil. */ + fprintf(fp, " 9\n$DIMCEN\n 40\n0.01\n"); /* Size of center mark/lines = 10 mil. */ + fprintf(fp, " 9\n$DIMTSZ\n 40\n0.01\n"); /* Dimensioning tick size = 10 mil; 0 = no ticks. */ + fprintf(fp, " 9\n$DIMTOL\n 70\n 0\n"); /* Dimension tolerances generated if nonzero. */ + fprintf(fp, " 9\n$DIMLIM\n 70\n 0\n"); /* Dimension limits generated if nonzero. */ + fprintf(fp, " 9\n$DIMTIH\n 70\n 0\n"); /* Text inside horizontal if nonzero. */ + fprintf(fp, " 9\n$DIMTOH\n 70\n 0\n"); /* Text outside horizontal if nonzero. */ + fprintf(fp, " 9\n$DIMSE1\n 70\n 0\n"); /* First extension line suppressed if nonzero. */ + fprintf(fp, " 9\n$DIMSE2\n 70\n 0\n"); /* Second extension line suppressed if nonzero. */ + fprintf(fp, " 9\n$DIMTAD\n 70\n 1\n"); /* Text above dimension line if nonzero. */ + fprintf(fp, " 9\n$DIMZIN\n 70\n 8\n"); /* Controls suppression of zeros for primary unit values. */ + fprintf(fp, " 9\n$DIMBLK\n 1\n\n"); /* Arrow block name. */ + fprintf(fp, " 9\n$DIMASO\n 70\n 1\n"); /* 1 = create associative dimensioning, 0 = draw individual entities. */ + fprintf(fp, " 9\n$DIMSHO\n 70\n 1\n"); /* 1 = Recompute dimensions while dragging, 0 = drag original image. */ + fprintf(fp, " 9\n$DIMPOST\n 1\n\n"); /* General dimensioning suffix. */ + fprintf(fp, " 9\n$DIMAPOST\n 1\n\n"); /* Alternate dimensioning suffix. */ + fprintf(fp, " 9\n$DIMALT\n 70\n 0\n"); /* Alternate unit dimensioning performed if nonzero. */ + fprintf(fp, " 9\n$DIMALTD\n 70\n 4\n"); /* Alternate unit decimal places. */ + fprintf(fp, " 9\n$DIMALTF\n 40\n0.0254\n"); /* Alternate unit scale factor = inch --> mm. */ + fprintf(fp, " 9\n$DIMLFAC\n 40\n1.0\n"); /* Linear measurements scale factor. */ + fprintf(fp, " 9\n$DIMTOFL\n 70\n 1\n"); /* If text outside extensions, force line extensions between extensions if nonzero. */ + fprintf(fp, " 9\n$DIMTVP\n 40\n0.0\n"); /* Text vertical position. */ + fprintf(fp, " 9\n$DIMTIX\n 70\n 0\n"); /* Force text inside extensions if nonzero. */ + fprintf(fp, " 9\n$DIMSOXD\n 70\n 0\n"); /* Suppress outside-extensions dimension lines if nonzero. */ + fprintf(fp, " 9\n$DIMSAH\n 70\n 0\n"); /* Use separate arrow blocks if nonzero. */ + fprintf(fp, " 9\n$DIMBLK1\n 1\n\n"); /* First arrow block name. */ + fprintf(fp, " 9\n$DIMBLK2\n 1\n\n"); /* Second arrow block name. */ + fprintf(fp, " 9\n$DIMSTYLE\n 2\nSTANDARD\n"); /* Dimension style name. */ + fprintf(fp, " 9\n$DIMCLRD\n 70\n 0\n"); /*Dimension line color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMCLRE\n 70\n 0\n"); /* Dimension extension line color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMCLRT\n 70\n 0\n"); /* Dimension text color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMTFAC\n 40\n1.0\n"); /* Dimension tolerance display scale factor. */ + fprintf(fp, " 9\n$DIMGAP\n 40\n25.0\n"); /* Dimension line gap = 25 mil. */ + fprintf(fp, " 9\n$DIMJUST\n 70\n 0\n"); /* Horizontal dimension text position: 0=above dimension line and center-justified between extension lines, 1=above dimension line and next to first extension line, 2=above dimension line and next to second extension line, 3=above and center-justified to first extension line, 4=above and center-justified to second extension line. */ + fprintf(fp, " 9\n$DIMSD1\n 70\n 0\n"); /* Suppression of first extension line: 0=not suppressed, 1=suppressed. */ + fprintf(fp, " 9\n$DIMSD2\n 70\n 0\n"); /* Suppression of second extension line: 0=not suppressed, 1=suppressed. */ + fprintf(fp, " 9\n$DIMTOLJ\n 70\n 1\n"); /* Vertical justification for tolerance values: 0=Top, 1=Middle, 2=Bottom. */ + fprintf(fp, " 9\n$DIMTZIN\n 70\n 0\n"); /* Controls suppression of zeros for tolerance values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + fprintf(fp, " 9\n$DIMALTZ\n 70\n 0\n"); /* Controls suppression of zeros for alternate unit dimension values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + fprintf(fp, " 9\n$DIMALTTZ\n 70\n 0\n"); /* Controls suppression of zeros for alternate tolerance values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + fprintf(fp, " 9\n$DIMFIT\n 70\n 3\n"); /* Placement of text and arrowheads; Possible values: 0 through 3. */ + fprintf(fp, " 9\n$DIMUPT\n 70\n 0\n"); /* Cursor functionality for user positioned text: 0=controls only the dimension line location, 1=controls the text position as well as the dimension line location. */ + fprintf(fp, " 9\n$DIMUNIT\n 70\n 2\n"); /* Units format for all dimension style family members except angular: 1 = Scientific; 2 = Decimal; 3 = Engineering; 4 = Architectural (stacked); 5 = Fractional (stacked); 6 = Architectural; 7 = Fractional. */ + fprintf(fp, " 9\n$DIMDEC\n 70\n 4\n"); /* Number of decimal places for the tolerance values of a primary units dimension. */ + fprintf(fp, " 9\n$DIMTDEC\n 70\n 4\n"); /* Number of decimal places to display the tolerance values. */ + fprintf(fp, " 9\n$DIMALTU\n 70\n 2\n"); /*Units format for alternate units of all dimension style family members except angular: 1 = Scientific; 2 = Decimal; 3 = Engineering; 4 = Architectural (stacked); 5 = Fractional (stacked); 6 = Architectural; 7 = Fractional. */ + fprintf(fp, " 9\n$DIMALTTD\n 70\n 2\n"); /*Number of decimal places for tolerance values of an alternate units dimension. */ + fprintf(fp, " 9\n$DIMTXSTY\n 7\nSTANDARD\n"); /* Dimension text style. */ + fprintf(fp, " 9\n$DIMAUNIT\n 70\n 0\n"); /* Angle format for angular dimensions: 0=Decimal degrees, 1=Degrees/minutes/seconds, 2=Gradians, 3=Radians, 4=Surveyor's units. */ + fprintf(fp, " 9\n$LUNITS\n 70\n 2\n"); /* Units format for coordinates and distances. */ + fprintf(fp, " 9\n$LUPREC\n 70\n 4\n"); /* Units precision for coordinates and distances */ + fprintf(fp, " 9\n$SKETCHINC\n 40\n1.0\n"); /* Sketch record increment. */ + fprintf(fp, " 9\n$FILLETRAD\n 40\n1.0\n"); /* Fillet radius. */ + fprintf(fp, " 9\n$AUNITS\n 70\n 0\n"); /* Units format for angles. */ + fprintf(fp, " 9\n$AUPREC\n 70\n 0\n"); /* Units precision for angles. */ + fprintf(fp, " 9\n$MENU\n 1\n.\n"); /* Name of menu file. */ + fprintf(fp, " 9\n$ELEVATION\n 40\n0.0\n"); /* Current elevation set by ELEV command. */ + fprintf(fp, " 9\n$PELEVATION\n 40\n0.0\n"); /* Current paper space elevation. */ + fprintf(fp, " 9\n$THICKNESS\n 40\n0.0\n"); /* Current thickness set by ELEV command. */ + fprintf(fp, " 9\n$LIMCHECK\n 70\n 0\n"); /* Nonzero if limits checking is on. */ + fprintf(fp, " 9\n$BLIPMODE\n 70\n 0\n"); /* Blip mode on if nonzero. */ + fprintf(fp, " 9\n$CHAMFERA\n 40\n10.0\n"); /* First chamfer distance. */ + fprintf(fp, " 9\n$CHAMFERB\n 40\n10.0\n"); /* Second chamfer distance. */ + fprintf(fp, " 9\n$CHAMFERC\n 40\n0.0\n"); /* Chamfer length. */ + fprintf(fp, " 9\n$CHAMFERD\n 40\n0.0\n"); /* Chamfer angle. */ + fprintf(fp, " 9\n$SKPOLY\n 70\n 0\n"); /* 0 = sketch lines, 1 = sketch polylines. */ + fprintf(fp, " 9\n$TDCREATE\n 40\n0.0\n"); /* Date/time of drawing creation. */ + fprintf(fp, " 9\n$TDUPDATE\n 40\n0.0\n"); /* Date/time of last drawing update. */ + fprintf(fp, " 9\n$TDINDWG\n 40\n0.0\n"); /* Cumulative editing time for this drawing. */ + fprintf(fp, " 9\n$TDUSRTIMER\n 40\n0.0\n"); /* User elapsed timer. */ + fprintf(fp, " 9\n$USRTIMER\n 70\n 1\n"); /* 0 = timer off, 1 = timer on. */ + fprintf(fp, " 9\n$ANGBASE\n 50\n0.0\n"); /* Angle 0 direction . */ + fprintf(fp, " 9\n$ANGDIR\n 70\n 0\n"); /* 1 = clockwise angles, 0 = counterclockwise. */ + fprintf(fp, " 9\n$PDMODE\n 70\n 98\n"); /* Point display mode. */ + fprintf(fp, " 9\n$PDSIZE\n 40\n0.0\n"); /* Point display size. */ + fprintf(fp, " 9\n$PLINEWID\n 40\n0.0\n"); /* Default polyline width. */ + fprintf(fp, " 9\n$COORDS\n 70\n 2\n"); /* Coordinate display: 0 = static, 1 = continuous update, 2 = "d +*
  • HEADER section + *
  • CLASSES section + *
  • TABLES section + *
      + *
    • VPORT table + *
    • LTYPE table + *
    • LAYER table + *
    • STYLE table + *
    • VIEW table + *
    • UCS table + *
    • APPID table + *
    • DIMSTYLE table + *
    + * + */ +static void dxf_write_header_metric_new() +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_header_metric_new () function.\n", __FILE__, __LINE__); +#endif + /* write a metric HEADER section */ + fprintf(fp, " 0\nSECTION\n"); + fprintf(fp, " 2\nHEADER\n"); /* Section name. */ + fprintf(fp, " 9\n$ACADVER\n 1\nAC1014\n"); /* AutoCAD drawing database version number. */ + fprintf(fp, " 9\n$ACADMAINTVER\n 70\n 0\n"); /* Maintenance version number. */ + fprintf(fp, " 9\n$DWGCODEPAGE\n 3\nANSI_1252\n"); /* Drawing code page. */ + fprintf(fp, " 9\n$INSBASE\n 10\n0.0\n 20\n0.0\n 30\n0.0\n"); /* Insertion base set by BASE command (in WCS). */ + fprintf(fp, " 9\n$EXTMIN\n 10\n0.0\n 20\n0.0\n 30\n0.0\n"); /* X, Y, and Z drawing extents lower-left corner (in WCS). */ + fprintf(fp, " 9\n$EXTMAX\n 10\n88.01056\n 20\n35.022217\n 30\n0.0\n"); /* X, Y, and Z drawing extents upper-right corner (in WCS). */ + fprintf(fp, " 9\n$LIMMIN\n 10\n0.0\n 20\n0.0\n"); /* XY drawing limits lower-left corner (in WCS). */ + fprintf(fp, " 9\n$LIMMAX\n 10\n420.0\n 20\n297.0\n"); /* XY drawing limits upper-right corner (in WCS). */ + fprintf(fp, " 9\n$ORTHOMODE\n 70\n 0\n"); /* Ortho mode on if nonzero. */ + fprintf(fp, " 9\n$REGENMODE\n 70\n 1\n"); /* REGENAUTO mode on if nonzero. */ + fprintf(fp, " 9\n$FILLMODE\n 70\n 1\n"); /* Fill mode on if nonzero. */ + fprintf(fp, " 9\n$QTEXTMODE\n 70\n 0\n"); /* Quick text mode on if nonzero. */ + fprintf(fp, " 9\n$MIRRTEXT\n 70\n 1\n"); /* Mirror text if nonzero. */ + fprintf(fp, " 9\n$DRAGMODE\n 70\n 2\n"); /* 0 = off, 1 = on, 2 = auto. */ + fprintf(fp, " 9\n$LTSCALE\n 40\n1.0\n"); /* Global linetype scale. */ + fprintf(fp, " 9\n$OSMODE\n 70\n 125\n"); /* Running object snap modes. */ + fprintf(fp, " 9\n$ATTMODE\n 70\n 1\n"); /* Attribute visibility: 0 = none, 1 = normal, 2 = all. */ + fprintf(fp, " 9\n$TEXTSIZE\n 40\n2.5\n"); /* Default text height = 2.5 mm. */ + fprintf(fp, " 9\n$TRACEWID\n 40\n1.0\n"); /* Default trace width. */ + fprintf(fp, " 9\n$TEXTSTYLE\n 7\nSTANDARD\n"); /* Current text style name. */ + fprintf(fp, " 9\n$CLAYER\n 8\n0\n"); /* Current layer name. */ + fprintf(fp, " 9\n$CELTYPE\n 6\nBYLAYER\n"); /* Entity linetype name, or BYBLOCK or BYLAYER. */ + fprintf(fp, " 9\n$CECOLOR\n 62\n 256\n"); /* Current entity color number: 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$CELTSCALE\n 40\n1.0\n"); /* Current entity linetype scale. */ + fprintf(fp, " 9\n$DELOBJ\n 70\n 1\n"); /* Controls object deletion: 0 = deleted, 1 = retained. */ + fprintf(fp, " 9\n$DISPSILH\n 70\n 0\n"); /* Controls the display of silhouette curves of body objects in wire-frame mode: 0 = Off, 1 = On. */ + fprintf(fp, " 9\n$DIMSCALE\n 40\n1.0\n"); /* Overall dimensioning scale factor. */ + fprintf(fp, " 9\n$DIMASZ\n 40\n2.5\n"); /* Dimensioning arrow size = 2.5 mm. */ + fprintf(fp, " 9\n$DIMEXO\n 40\n0.625\n"); /* Extension line offset = 0.625 mm. */ + fprintf(fp, " 9\n$DIMDLI\n 40\n3.75\n"); /* Dimension line increment = 3.75 mm. */ + fprintf(fp, " 9\n$DIMRND\n 40\n0.0\n"); /* Rounding value for dimension distances. */ + fprintf(fp, " 9\n$DIMDLE\n 40\n0.0\n"); /* Dimension line extension */ + fprintf(fp, " 9\n$DIMEXE\n 40\n1.25\n"); /* Extension line extension = 1.25 mm. */ + fprintf(fp, " 9\n$DIMTP\n 40\n0.0\n"); /* Plus tolerance. */ + fprintf(fp, " 9\n$DIMTM\n 40\n0.0\n"); /* Minus tolerance. */ + fprintf(fp, " 9\n$DIMTXT\n 40\n2.5\n"); /* Dimensioning text height = 2.5 mm. */ + fprintf(fp, " 9\n$DIMCEN\n 40\n2.5\n"); /* Size of center mark/lines = 2.5 mm. */ + fprintf(fp, " 9\n$DIMTSZ\n 40\n0.0\n"); /* Dimensioning tick size; 0 = no ticks. */ + fprintf(fp, " 9\n$DIMTOL\n 70\n 0\n"); /* Dimension tolerances generated if nonzero. */ + fprintf(fp, " 9\n$DIMLIM\n 70\n 0\n"); /* Dimension limits generated if nonzero. */ + fprintf(fp, " 9\n$DIMTIH\n 70\n 0\n"); /* Text inside horizontal if nonzero. */ + fprintf(fp, " 9\n$DIMTOH\n 70\n 0\n"); /* Text outside horizontal if nonzero. */ + fprintf(fp, " 9\n$DIMSE1\n 70\n 0\n"); /* First extension line suppressed if nonzero. */ + fprintf(fp, " 9\n$DIMSE2\n 70\n 0\n"); /* Second extension line suppressed if nonzero. */ + fprintf(fp, " 9\n$DIMTAD\n 70\n 1\n"); /* Text above dimension line if nonzero. */ + fprintf(fp, " 9\n$DIMZIN\n 70\n 8\n"); /* Controls suppression of zeros for primary unit values. */ + fprintf(fp, " 9\n$DIMBLK\n 1\n\n"); /* Arrow block name. */ + fprintf(fp, " 9\n$DIMASO\n 70\n 1\n"); /* 1 = create associative dimensioning, 0 = draw individual entities. */ + fprintf(fp, " 9\n$DIMSHO\n 70\n 1\n"); /* 1 = Recompute dimensions while dragging, 0 = drag original image. */ + fprintf(fp, " 9\n$DIMPOST\n 1\n\n"); /* General dimensioning suffix. */ + fprintf(fp, " 9\n$DIMAPOST\n 1\n\n"); /* Alternate dimensioning suffix. */ + fprintf(fp, " 9\n$DIMALT\n 70\n 0\n"); /* Alternate unit dimensioning performed if nonzero. */ + fprintf(fp, " 9\n$DIMALTD\n 70\n 4\n") /* Alternate unit decimal places. */ ; + fprintf(fp, " 9\n$DIMALTF\n 40\n0.0394\n") /* Alternate unit scale factor (mm --> mil). */ ; + fprintf(fp, " 9\n$DIMLFAC\n 40\n1.0\n"); /* Linear measurements scale factor. */ + fprintf(fp, " 9\n$DIMTOFL\n 70\n 1\n"); /* If text outside extensions, force line extensions between extensions if nonzero. */ + fprintf(fp, " 9\n$DIMTVP\n 40\n0.0\n"); /* Text vertical position. */ + fprintf(fp, " 9\n$DIMTIX\n 70\n 0\n"); /* Force text inside extensions if nonzero. */ + fprintf(fp, " 9\n$DIMSOXD\n 70\n 0\n"); /* Suppress outside-extensions dimension lines if nonzero. */ + fprintf(fp, " 9\n$DIMSAH\n 70\n 0\n"); /* Use separate arrow blocks if nonzero. */ + fprintf(fp, " 9\n$DIMBLK1\n 1\n\n"); /* First arrow block name. */ + fprintf(fp, " 9\n$DIMBLK2\n 1\n\n"); /* Second arrow block name. */ + fprintf(fp, " 9\n$DIMSTYLE\n 2\nSTANDARD\n"); /* Dimension style name. */ + fprintf(fp, " 9\n$DIMCLRD\n 70\n 0\n"); /* Dimension line color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMCLRE\n 70\n 0\n"); /* Dimension extension line color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMCLRT\n 70\n 0\n"); /* Dimension text color: range is 0 = BYBLOCK, 256 = BYLAYER. */ + fprintf(fp, " 9\n$DIMTFAC\n 40\n1.0\n"); /* Dimension tolerance display scale factor. */ + fprintf(fp, " 9\n$DIMGAP\n 40\n0.625\n") /* Dimension line gap. */ ; + fprintf(fp, " 9\n$DIMJUST\n 70\n 0\n"); /* Horizontal dimension text position: 0 = above dimension line and center-justified between extension lines, 1 = above dimension line and next to first extension line, 2=above dimension line and next to second extension line, 3 = above and center-justified to first extension line, 4 = above and center-justified to second extension line. */ + fprintf(fp, " 9\n$DIMSD1\n 70\n 0\n"); /* Suppression of first extension line: 0 = not suppressed, 1 = suppressed. */ + fprintf(fp, " 9\n$DIMSD2\n 70\n 0\n"); /* Suppression of second extension line: 0 = not suppressed, 1 = suppressed. */ + fprintf(fp, " 9\n$DIMTOLJ\n 70\n 1\n"); /* Vertical justification for tolerance values: 0 = Top, 1 = Middle, 2 = Bottom. */ + fprintf(fp, " 9\n$DIMTZIN\n 70\n 0\n"); /* Controls suppression of zeros for tolerance values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + fprintf(fp, " 9\n$DIMALTZ\n 70\n 0\n"); /* Controls suppression of zeros for alternate unit dimension values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + fprintf(fp, + " 9\n$DIMALTTZ\n 70\n 0\n") + /* Controls suppression of zeros for alternate tolerance values: 0 = Suppresses zero feet and precisely zero inches; 1 = Includes zero feet and precisely zero inches; 2 = Includes zero feet and suppresses zero inches; 3 = Includes zero inches and suppresses zero feet. */ + ; + fprintf(fp, " 9\n$DIMFIT\n 70\n 3\n"); /* Placement of text and arrowheads; Possible values: 0 through 3. */ + fprintf(fp, " 9\n$DIMUPT\n 70\n 0\n"); /* Cursor functionality for user positioned text: 0=controls only the dimension line location, 1=controls the text position as well as the dimension line location. */ + fprintf(fp, " 9\n$DIMUNIT\n 70\n 2\n"); /* Units format for all dimension style family members except angular: 1 = Scientific; 2 = Decimal; 3 = Engineering; 4 = Architectural (stacked); 5 = Fractional (stacked); 6 = Architectural; 7 = Fractional. */ + fprintf(fp, " 9\n$DIMDEC\n 70\n 4\n"); /* Number of decimal places for the tolerance values of a primary units dimension. */ + fprintf(fp, " 9\n$DIMTDEC\n 70\n 4\n"); /* Number of decimal places to display the tolerance values. */ + fprintf(fp, " 9\n$DIMALTU\n 70\n 2\n"); /*Units format for alternate units of all dimension style family members except angular: 1 = Scientific; 2 = Decimal; 3 = Engineering; 4 = Architectural (stacked); 5 = Fractional (stacked); 6 = Architectural; 7 = Fractional. */ + fprintf(fp, " 9\n$DIMALTTD\n 70\n 2\n"); /*Number of decimal places for tolerance values of an alternate units dimension. */ + fprintf(fp, " 9\n$DIMTXSTY\n 7\nSTANDARD\n"); /* Dimension text style. */ + fprintf(fp, " 9\n$DIMAUNIT\n 70\n 0\n"); /* Angle format for angular dimensions: 0 = Decimal degrees, 1 = Degrees/minutes/seconds, 2 = Gradians, 3=Radians, 4 = Surveyor's units. */ + fprintf(fp, " 9\n$LUNITS\n 70\n 2\n"); /* Units format for coordinates and distances. */ + fprintf(fp, " 9\n$LUPREC\n 70\n 4\n"); /* Units precision for coordinates and distances. */ + fprintf(fp, " 9\n$SKETCHINC\n 40\n1.0\n"); /* Sketch record increment. */ + fprintf(fp, " 9\n$FILLETRAD\n 40\n1.0\n"); /* Fillet radius. */ + fprintf(fp, " 9\n$AUNITS\n 70\n 0\n"); /* Units format for angles. */ + fprintf(fp, " 9\n$AUPREC\n 70\n 0\n"); /* Units precision for angles. */ + fprintf(fp, " 9\n$MENU\n 1\n.\n"); /* Name of menu file. */ + fprintf(fp, " 9\n$ELEVATION\n 40\n0.0\n"); /* Current elevation set by ELEV command. */ + fprintf(fp, " 9\n$PELEVATION\n 40\n0.0\n") /* Current paper space elevation. */ ; + fprintf(fp, " 9\n$THICKNESS\n 40\n0.0\n"); /* Current thickness set by ELEV command. */ + fprintf(fp, " 9\n$LIMCHECK\n 70\n 0\n"); /* Nonzero if limits checking is on. */ + fprintf(fp, " 9\n$BLIPMODE\n 70\n 0\n"); /* Blip mode on if nonzero. */ + fprintf(fp, " 9\n$CHAMFERA\n 40\n10.0\n"); /* First chamfer distance. */ + fprintf(fp, " 9\n$CHAMFERB\n 40\n10.0\n"); /* Second chamfer distance. */ + fprintf(fp, " 9\n$CHAMFERC\n 40\n0.0\n"); /* Chamfer length. */ + fprintf(fp, " 9\n$CHAMFERD\n 40\n0.0\n"); /* Chamfer angle. */ + fprintf(fp, " 9\n$SKPOLY\n 70\n 0\n"); /* 0 = sketch lines, 1 = sketch polylines. */ + fprintf(fp, " 9\n$TDCREATE\n 40\n0.0\n"); /* Date/time of drawing creation. */ + fprintf(fp, " 9\n$TDUPDATE\n 40\n0.0\n"); /* Date/time of last drawing update. */ + fprintf(fp, " 9\n$TDINDWG\n 40\n0.0\n"); /* Cumulative editing time for this drawing. */ + fprintf(fp, " 9\n$TDUSRTIMER\n 40\n0.0\n"); /* User elapsed timer. */ + fprintf(fp, " 9\n$USRTIMER\n 70\n 1\n"); /* 0 = timer off, 1 = timer on. */ + fprintf(fp, " 9\n$ANGBASE\n 50\n0.0\n"); /* Angle 0 direction . */ + fprintf(fp, " 9\n$ANGDIR\n 70\n 0\n"); /* 1 = clockwise angles, 0 = counterclockwise. */ + fprintf(fp, " 9\n$PDMODE\n 70\n 98\n"); /* Point display mode. */ + fprintf(fp, " 9\n$PDSIZE\n 40\n0.0\n"); /* Point display size. */ + fprintf(fp, " 9\n$PLINEWID\n 40\n0.0\n"); /* Default polyline width. */ + fprintf(fp, " 9\n$COORDS\n 70\n 2\n"); /* Coordinate display: 0 = static, 1 = continuous update, 2 = "d + *
  • HEADER section + *
  • CLASSES section + *
  • TABLES section + *
      + *
    • VPORT table + *
    • LTYPE table + *
    • LAYER table + *
    • STYLE table + *
    • VIEW table + *
    • UCS table + *
    • APPID table + *
    • DIMSTYLE table + *
    + * + * Continue from here with writing a BLOCK_RECORD table and close the section + * with an ENDSEC marker. + */ +static void dxf_write_header() +{ + FILE *f_temp; + static char *dxf_header_filename; + + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_header () function.\n", __FILE__, __LINE__); +#endif + if (dxf_metric) { + dxf_header_filename = pcb_strdup("hid/dxf/template/metric_header.dxf"); + } + else { + dxf_header_filename = pcb_strdup("hid/dxf/template/imperial_header.dxf"); + } + /* check if template metric header file exists and open file + * read-only */ + f_temp = fopen(dxf_header_filename, "r"); + if (f_temp) { + char buff[1024]; + /* do until EOF of the template file: + * copy line by line from template file (f_temp) to + * destination file (fp) */ + while (!feof(f_temp)) { + int len = fread(buff, 1, sizeof(buff), f_temp); + if (len > 0) + fwrite(buff, 1, len, fp); + } + /* when we're done close the template file */ + fclose(f_temp); + } + else { + pcb_gui->log("Error in dxf_write_header_from_template (): cannot open file %s for reading.\n", dxf_header_filename); + if (dxf_metric) { + dxf_write_header_metric_new(); + } + else { + dxf_write_header_imperial_new(); + } + } + /* write a block record table */ + dxf_write_table_block_record(fp); + /* write ENDSEC marker to close the header */ + dxf_write_endsection(fp); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_header () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for an imperial DXF footer. + * + * Included sections are:\n + *
      + *
    • OBJECTS section + *
    • THUMBNAILIMAGE section + *
    + */ +static void dxf_write_footer_imperial_new() +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_footer_imperial_new () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, "0\nSECTION\n"); + fprintf(fp, " 2\nOBJECTS\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\nC\n"); + fprintf(fp, "330\n0\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nACAD_COLOR\n"); + fprintf(fp, "350\n75\n"); + fprintf(fp, " 3\nACAD_GROUP\n"); + fprintf(fp, "350\nD\n"); + fprintf(fp, " 3\nACAD_LAYOUT\n"); + fprintf(fp, "350\n76\n"); + fprintf(fp, " 3\nACAD_MATERIAL\n"); + fprintf(fp, "350\n74\n"); + fprintf(fp, " 3\nACAD_MLINESTYLE\n"); + fprintf(fp, "350\n1B\n"); + fprintf(fp, "3\nACAD_PLOTSETTINGS\n"); + fprintf(fp, "350\n77\n"); + fprintf(fp, " 3\nACAD_PLOTSTYLENAME\n"); + fprintf(fp, "350\n72\n"); + fprintf(fp, " 3\nAVE_ACITABLE\n"); + fprintf(fp, "350\n51\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n75\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\nD\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n76\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nLayout1\n"); + fprintf(fp, "350\n79\n"); + fprintf(fp, " 3\nModel\n"); + fprintf(fp, "350\n78\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n74\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n1B\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nSTANDARD\n"); + fprintf(fp, "350\n1C\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n77\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nACDBDICTIONARYWDFLT\n"); + fprintf(fp, " 5\n72\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nNormal\n"); + fprintf(fp, "350\n73\n"); + fprintf(fp, "100\nAcDbDictionaryWithDefault\n"); + fprintf(fp, "340\n73\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n51\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nLAYOUT\n"); + fprintf(fp, " 5\n79\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "100\nAcDbPlotSettings\n"); + fprintf(fp, " 1\n\n"); + fprintf(fp, " 2\n\\\\NO_SERVER\\NO_PRINTER\n"); + fprintf(fp, " 4\n\n"); + fprintf(fp, " 6\n\n"); + fprintf(fp, " 40\n0.0\n"); + fprintf(fp, " 41\n0.0\n"); + fprintf(fp, " 42\n0.0\n"); + fprintf(fp, " 43\n0.0\n"); + fprintf(fp, " 44\n0.0\n"); + fprintf(fp, " 45\n0.0\n"); + fprintf(fp, " 46\n0.0\n"); + fprintf(fp, " 47\n0.0\n"); + fprintf(fp, " 48\n0.0\n"); + fprintf(fp, " 49\n0.0\n"); + fprintf(fp, "140\n0.0\n"); + fprintf(fp, "141\n0.0\n"); + fprintf(fp, "142\n1.0\n"); + fprintf(fp, "143\n1.0\n"); + fprintf(fp, " 70\n 688\n"); + fprintf(fp, " 72\n 0\n"); + fprintf(fp, " 73\n 0\n"); + fprintf(fp, " 74\n 5\n"); + fprintf(fp, " 7\n\n"); + fprintf(fp, " 75\n 16\n"); + fprintf(fp, "147\n1.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, " 77\n 2\n"); + fprintf(fp, " 78\n 300\n"); + fprintf(fp, "148\n0.0\n"); + fprintf(fp, "149\n0.0\n"); + fprintf(fp, "100\nAcDbLayout\n"); + fprintf(fp, " 1\nLayout1\n"); + fprintf(fp, " 70\n 1\n"); + fprintf(fp, " 71\n 1\n"); + fprintf(fp, " 10\n0.0\n"); + fprintf(fp, " 20\n0.0\n"); + fprintf(fp, " 11\n17.0\n"); + fprintf(fp, " 21\n11.0\n"); + fprintf(fp, " 12\n0.0\n"); + fprintf(fp, " 22\n0.0\n"); + fprintf(fp, " 32\n0.0\n"); + fprintf(fp, " 14\n1.000000000000000E+20\n"); + fprintf(fp, " 24\n1.000000000000000E+20\n"); + fprintf(fp, " 34\n1.000000000000000E+20\n"); + fprintf(fp, " 15\n-1.000000000000000E+20\n"); + fprintf(fp, " 25\n-1.000000000000000E+20\n"); + fprintf(fp, " 35\n-1.000000000000000E+20\n"); + fprintf(fp, "146\n0.0\n"); + fprintf(fp, " 13\n0.0\n"); + fprintf(fp, " 23\n0.0\n"); + fprintf(fp, " 33\n0.0\n"); + fprintf(fp, " 16\n1.0\n"); + fprintf(fp, " 26\n0.0\n"); + fprintf(fp, " 36\n0.0\n"); + fprintf(fp, " 17\n0.0\n"); + fprintf(fp, " 27\n1.0\n"); + fprintf(fp, " 37\n0.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, "330\n15\n"); + fprintf(fp, " 0\nLAYOUT\n"); + fprintf(fp, " 5\n78\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "100\nAcDbPlotSettings\n"); + fprintf(fp, " 1\n\n"); + fprintf(fp, " 2\n\\\\NO_SERVER\\NO_PRINTER\n"); + fprintf(fp, " 4\n\n"); + fprintf(fp, " 6\n\n"); + fprintf(fp, " 40\n0.0\n"); + fprintf(fp, " 41\n0.0\n"); + fprintf(fp, " 42\n0.0\n"); + fprintf(fp, " 43\n0.0\n"); + fprintf(fp, " 44\n0.0\n"); + fprintf(fp, " 45\n0.0\n"); + fprintf(fp, " 46\n0.0\n"); + fprintf(fp, " 47\n0.0\n"); + fprintf(fp, " 48\n0.0\n"); + fprintf(fp, " 49\n0.0\n"); + fprintf(fp, "140\n0.0\n"); + fprintf(fp, "141\n0.0\n"); + fprintf(fp, "142\n1.0\n"); + fprintf(fp, "143\n1.0\n"); + fprintf(fp, " 70\n 1712\n"); + fprintf(fp, " 72\n 0\n"); + fprintf(fp, " 73\n 0\n"); + fprintf(fp, " 74\n 0\n"); + fprintf(fp, " 7\n\n"); + fprintf(fp, " 75\n 0\n"); + fprintf(fp, "147\n1.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, " 77\n 2\n"); + fprintf(fp, " 78\n 300\n"); + fprintf(fp, "148\n0.0\n"); + fprintf(fp, "149\n0.0\n"); + fprintf(fp, "100\nAcDbLayout\n"); + fprintf(fp, " 1\nModel\n"); + fprintf(fp, " 70\n 1\n"); + fprintf(fp, " 71\n 0\n"); + fprintf(fp, " 10\n0.0\n"); + fprintf(fp, " 20\n0.0\n"); + fprintf(fp, " 11\n17.0\n"); + fprintf(fp, " 21\n11.0\n"); + fprintf(fp, " 12\n0.0\n"); + fprintf(fp, " 22\n0.0\n"); + fprintf(fp, " 32\n0.0\n"); + fprintf(fp, " 14\n0.0\n"); + fprintf(fp, " 24\n0.0\n"); + fprintf(fp, " 34\n0.0\n"); + fprintf(fp, " 15\n0.0\n"); + fprintf(fp, " 25\n0.0\n"); + fprintf(fp, " 35\n0.0\n"); + fprintf(fp, "146\n0.0\n"); + fprintf(fp, " 13\n0.0\n"); + fprintf(fp, " 23\n0.0\n"); + fprintf(fp, " 33\n0.0\n"); + fprintf(fp, " 16\n1.0\n"); + fprintf(fp, " 26\n0.0\n"); + fprintf(fp, " 36\n0.0\n"); + fprintf(fp, " 17\n0.0\n"); + fprintf(fp, " 27\n1.0\n"); + fprintf(fp, " 37\n0.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, "330\n18\n"); + fprintf(fp, " 0\nMLINESTYLE\n"); + fprintf(fp, " 5\n1C\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n1B\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n1B\n"); + fprintf(fp, "100\nAcDbMlineStyle\n"); + fprintf(fp, " 2\nSTANDARD\n"); + fprintf(fp, " 70\n 0\n"); + fprintf(fp, " 3\n\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 51\n90.0\n"); + fprintf(fp, " 52\n90.0\n"); + fprintf(fp, " 71\n 2\n"); + fprintf(fp, " 49\n0.5\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 6\nBYLAYER\n"); + fprintf(fp, " 49\n-0.5\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 6\nBYLAYER\n"); + fprintf(fp, " 0\nACDBPLACEHOLDER\n"); + fprintf(fp, " 5\n73\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n72\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n72\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_footer_imperial_new () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a metric DXF footer. + * + * Included sections are:\n + *
      + *
    • OBJECTS section + *
    • THUMBNAILIMAGE section + *
    + */ +static void dxf_write_footer_metric_new() +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_footer_metric_new () function.\n", __FILE__, __LINE__); +#endif + fprintf(fp, "0\nSECTION\n"); + fprintf(fp, " 2\nOBJECTS\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\nC\n"); + fprintf(fp, "330\n0\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nACAD_COLOR\n"); + fprintf(fp, "350\n75\n"); + fprintf(fp, " 3\nACAD_GROUP\n"); + fprintf(fp, "350\nD\n"); + fprintf(fp, " 3\nACAD_LAYOUT\n"); + fprintf(fp, "350\n76\n"); + fprintf(fp, " 3\nACAD_MATERIAL\n"); + fprintf(fp, "350\n74\n"); + fprintf(fp, " 3\nACAD_MLINESTYLE\n"); + fprintf(fp, "350\n1B\n"); + fprintf(fp, "3\nACAD_PLOTSETTINGS\n"); + fprintf(fp, "350\n77\n"); + fprintf(fp, " 3\nACAD_PLOTSTYLENAME\n"); + fprintf(fp, "350\n72\n"); + fprintf(fp, " 3\nAVE_ACITABLE\n"); + fprintf(fp, "350\n51\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n75\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\nD\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n76\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nLayout1\n"); + fprintf(fp, "350\n79\n"); + fprintf(fp, " 3\nModel\n"); + fprintf(fp, "350\n78\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n74\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n1B\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nSTANDARD\n"); + fprintf(fp, "350\n1C\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n77\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nACDBDICTIONARYWDFLT\n"); + fprintf(fp, " 5\n72\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 3\nNormal\n"); + fprintf(fp, "350\n73\n"); + fprintf(fp, "100\nAcDbDictionaryWithDefault\n"); + fprintf(fp, "340\n73\n"); + fprintf(fp, " 0\nDICTIONARY\n"); + fprintf(fp, " 5\n51\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\nC\n"); + fprintf(fp, "100\nAcDbDictionary\n"); + fprintf(fp, "281\n 1\n"); + fprintf(fp, " 0\nLAYOUT\n"); + fprintf(fp, " 5\n79\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "100\nAcDbPlotSettings\n"); + fprintf(fp, " 1\n\n"); + fprintf(fp, " 2\n\\\\NO_SERVER\\NO_PRINTER\n"); + fprintf(fp, " 4\n\n"); + fprintf(fp, " 6\n\n"); + fprintf(fp, " 40\n0.0\n"); + fprintf(fp, " 41\n0.0\n"); + fprintf(fp, " 42\n0.0\n"); + fprintf(fp, " 43\n0.0\n"); + fprintf(fp, " 44\n0.0\n"); + fprintf(fp, " 45\n0.0\n"); + fprintf(fp, " 46\n0.0\n"); + fprintf(fp, " 47\n0.0\n"); + fprintf(fp, " 48\n0.0\n"); + fprintf(fp, " 49\n0.0\n"); + fprintf(fp, "140\n0.0\n"); + fprintf(fp, "141\n0.0\n"); + fprintf(fp, "142\n1.0\n"); + fprintf(fp, "143\n1.0\n"); + fprintf(fp, " 70\n 688\n"); + fprintf(fp, " 72\n 0\n"); + fprintf(fp, " 73\n 0\n"); + fprintf(fp, " 74\n 5\n"); + fprintf(fp, " 7\n\n"); + fprintf(fp, " 75\n 16\n"); + fprintf(fp, "147\n1.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, " 77\n 2\n"); + fprintf(fp, " 78\n 300\n"); + fprintf(fp, "148\n0.0\n"); + fprintf(fp, "149\n0.0\n"); + fprintf(fp, "100\nAcDbLayout\n"); + fprintf(fp, " 1\nLayout1\n"); + fprintf(fp, " 70\n 1\n"); + fprintf(fp, " 71\n 1\n"); + fprintf(fp, " 10\n0.0\n"); + fprintf(fp, " 20\n0.0\n"); + fprintf(fp, " 11\n420.0\n"); + fprintf(fp, " 21\n297.0\n"); + fprintf(fp, " 12\n0.0\n"); + fprintf(fp, " 22\n0.0\n"); + fprintf(fp, " 32\n0.0\n"); + fprintf(fp, " 14\n1.000000000000000E+20\n"); + fprintf(fp, " 24\n1.000000000000000E+20\n"); + fprintf(fp, " 34\n1.000000000000000E+20\n"); + fprintf(fp, " 15\n-1.000000000000000E+20\n"); + fprintf(fp, " 25\n-1.000000000000000E+20\n"); + fprintf(fp, " 35\n-1.000000000000000E+20\n"); + fprintf(fp, "146\n0.0\n"); + fprintf(fp, " 13\n0.0\n"); + fprintf(fp, " 23\n0.0\n"); + fprintf(fp, " 33\n0.0\n"); + fprintf(fp, " 16\n1.0\n"); + fprintf(fp, " 26\n0.0\n"); + fprintf(fp, " 36\n0.0\n"); + fprintf(fp, " 17\n0.0\n"); + fprintf(fp, " 27\n1.0\n"); + fprintf(fp, " 37\n0.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, "330\n15\n"); + fprintf(fp, " 0\nLAYOUT\n"); + fprintf(fp, " 5\n78\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n76\n"); + fprintf(fp, "100\nAcDbPlotSettings\n"); + fprintf(fp, " 1\n\n"); + fprintf(fp, " 2\n\\\\NO_SERVER\\NO_PRINTER\n"); + fprintf(fp, " 4\n\n"); + fprintf(fp, " 6\n\n"); + fprintf(fp, " 40\n0.0\n"); + fprintf(fp, " 41\n0.0\n"); + fprintf(fp, " 42\n0.0\n"); + fprintf(fp, " 43\n0.0\n"); + fprintf(fp, " 44\n0.0\n"); + fprintf(fp, " 45\n0.0\n"); + fprintf(fp, " 46\n0.0\n"); + fprintf(fp, " 47\n0.0\n"); + fprintf(fp, " 48\n0.0\n"); + fprintf(fp, " 49\n0.0\n"); + fprintf(fp, "140\n0.0\n"); + fprintf(fp, "141\n0.0\n"); + fprintf(fp, "142\n1.0\n"); + fprintf(fp, "143\n1.0\n"); + fprintf(fp, " 70\n 1712\n"); + fprintf(fp, " 72\n 0\n"); + fprintf(fp, " 73\n 0\n"); + fprintf(fp, " 74\n 0\n"); + fprintf(fp, " 7\n\n"); + fprintf(fp, " 75\n 0\n"); + fprintf(fp, "147\n1.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, " 77\n 2\n"); + fprintf(fp, " 78\n 300\n"); + fprintf(fp, "148\n0.0\n"); + fprintf(fp, "149\n0.0\n"); + fprintf(fp, "100\nAcDbLayout\n"); + fprintf(fp, " 1\nModel\n"); + fprintf(fp, " 70\n 1\n"); + fprintf(fp, " 71\n 0\n"); + fprintf(fp, " 10\n0.0\n"); + fprintf(fp, " 20\n0.0\n"); + fprintf(fp, " 11\n12.0\n"); + fprintf(fp, " 21\n9.0\n"); + fprintf(fp, " 12\n0.0\n"); + fprintf(fp, " 22\n0.0\n"); + fprintf(fp, " 32\n0.0\n"); + fprintf(fp, " 14\n0.0\n"); + fprintf(fp, " 24\n0.0\n"); + fprintf(fp, " 34\n0.0\n"); + fprintf(fp, " 15\n0.0\n"); + fprintf(fp, " 25\n0.0\n"); + fprintf(fp, " 35\n0.0\n"); + fprintf(fp, "146\n0.0\n"); + fprintf(fp, " 13\n0.0\n"); + fprintf(fp, " 23\n0.0\n"); + fprintf(fp, " 33\n0.0\n"); + fprintf(fp, " 16\n1.0\n"); + fprintf(fp, " 26\n0.0\n"); + fprintf(fp, " 36\n0.0\n"); + fprintf(fp, " 17\n0.0\n"); + fprintf(fp, " 27\n1.0\n"); + fprintf(fp, " 37\n0.0\n"); + fprintf(fp, " 76\n 0\n"); + fprintf(fp, "330\n18\n"); + fprintf(fp, " 0\nMLINESTYLE\n"); + fprintf(fp, " 5\n1C\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n1B\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n1B\n"); + fprintf(fp, "100\nAcDbMlineStyle\n"); + fprintf(fp, " 2\nSTANDARD\n"); + fprintf(fp, " 70\n 0\n"); + fprintf(fp, " 3\n\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 51\n90.0\n"); + fprintf(fp, " 52\n90.0\n"); + fprintf(fp, " 71\n 2\n"); + fprintf(fp, " 49\n0.5\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 6\nBYLAYER\n"); + fprintf(fp, " 49\n-0.5\n"); + fprintf(fp, " 62\n 256\n"); + fprintf(fp, " 6\nBYLAYER\n"); + fprintf(fp, " 0\nACDBPLACEHOLDER\n"); + fprintf(fp, " 5\n73\n"); + fprintf(fp, "102\n{ACAD_REACTORS\n"); + fprintf(fp, "330\n72\n"); + fprintf(fp, "102\n}\n"); + fprintf(fp, "330\n72\n"); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_footer_metric_new () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a DXF footer. + * + * Depending on the metric/imperial units setting a footer will be + * appended to a DXF file.\n + * If a custom metric/imperial DXF footer file is available this will be + * used, if not aavailable a fall back functions will be called for + * appending a default metric/imperial footer. + */ +static void dxf_write_footer() +{ + FILE *f_temp; + char *temp = NULL; + static char *dxf_footer_filename; + + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_footer () function.\n", __FILE__, __LINE__); +#endif + if (dxf_metric) { + dxf_footer_filename = pcb_strdup("hid/dxf/template/metric_footer.dxf"); + } + else { + dxf_footer_filename = pcb_strdup("hid/dxf/template/imperial_footer.dxf"); + } + /* check if template metric footer file exists and open file + * read-only */ + f_temp = fopen(dxf_footer_filename, "r"); + if (f_temp) { + /* do until EOF of the template file: + * copy line by line from template file (f_temp) to + * destination file (fp) */ + while (!feof(f_temp)) { + fscanf(f_temp, "%s", temp); + fprintf(fp, "%s", temp); + } + /* when we're done close the template file */ + fclose(f_temp); + } + else { + pcb_gui->log("Error in dxf_write_footer (): cannot open file %s for reading.\n", dxf_footer_filename); + if (dxf_metric) { + dxf_write_footer_metric_new(); + } + else { + dxf_write_footer_imperial_new(); + } + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_footer () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for an insert entity. + */ +static void dxf_write_insert(FILE * fp, + /*!< file pointer to output file (or device). */ + int id_code, + /*!< group code = 5. */ + char *block_name, + /*!< group code = 2. */ + char *linetype, + /*!< group code = 6\n + * optional, if omitted defaults to \c BYLAYER. */ + char *layer, + /*!< group code = 8. */ + double x0, + /*!< group code = 10\n + * base point. */ + double y0, + /*!< group code = 20\n + * base point. */ + double z0, + /*!< group code = 30\n + * base point. */ + double thickness, + /*!< group code = 39\n + * optional, if omitted defaults to 0.0. */ + double rel_x_scale, + /*!< group code = 41\n + * optional, if omitted defaults to 1.0. */ + double rel_y_scale, + /*!< group code = 42\n + * optional, if omitted defaults to 1.0. */ + double rel_z_scale, + /*!< group code = 43\n + * optional, if omitted defaults to 1.0. */ + double column_spacing, + /*!< group code = 44\n + * optional, if omitted defaults to 0.0. */ + double row_spacing, + /*!< group code = 45\n + * optional, if omitted defaults to 0.0. */ + double rot_angle, + /*!< group code = 50\n + * optional, if omitted defaults to 0.0. */ + int color, + /*!< group code = 62\n + * optional, if omitted defaults to \c BYLAYER. */ + int attribute_follows, + /*!< group code = 66\n + * optional, if omitted defaults to 0. */ + int paperspace, + /*!< group code = 67\n + * optional, if omitted defaults to 0 (modelspace). */ + int columns, + /*!< group code = 70\n + * optional, if omitted defaults to 1. */ + int rows + /*!< group code = 71\n + * optional, if omitted defaults to 1. */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_insert () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with ID code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("INSERT"); + if (strcmp(block_name, "") == 0) { + fprintf(stderr, "Warning: empty block name string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is discarded from output.\n", dxf_entity_name); + return; + } + if (strcmp(layer, "") == 0) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0.\n", dxf_entity_name); + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + if (rel_x_scale == 0.0) { + fprintf(stderr, "Warning: relative X-scale factor has a value of 0.0 for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " default relative X-scale of 1.0 applied to %s entity.\n", dxf_entity_name); + rel_x_scale = 1.0; + } + if (rel_y_scale == 0.0) { + fprintf(stderr, "Warning: relative Y-scale factor has a value of 0.0 for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " default relative Y-scale of 1.0 applied to %s entity.\n", dxf_entity_name); + rel_y_scale = 1.0; + } + if (rel_z_scale == 0.0) { + fprintf(stderr, "Warning: relative Z-scale factor has a value of 0.0 for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " default relative Z-scale of 1.0 applied to %s entity.\n", dxf_entity_name); + rel_z_scale = 1.0; + } + if ((columns > 1) && (column_spacing == 0.0)) { + fprintf(stderr, + "Warning: number of columns is greater than 1 and the column spacing has a value of 0.0 for the %s entity with id-code: %x\n", + dxf_entity_name, id_code); + fprintf(stderr, " default number of columns value of 1 applied to %s entity.\n", dxf_entity_name); + columns = 1; + } + if ((rows > 1) && (row_spacing == 0.0)) { + fprintf(stderr, + "Warning: number of rows is greater than 1 and the row spacing has a value of 0.0 for the %s entity with id-code: %x\n", + dxf_entity_name, id_code); + fprintf(stderr, " default number of rows value of 1 applied to %s entity.\n", dxf_entity_name); + rows = 1; + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + fprintf(fp, " 2\n%s\n", block_name); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + if (rel_x_scale != 1.0) { + fprintf(fp, " 41\n%f\n", rel_x_scale); + } + if (rel_y_scale != 1.0) { + fprintf(fp, " 42\n%f\n", rel_y_scale); + } + if (rel_z_scale != 1.0) { + fprintf(fp, " 43\n%f\n", rel_z_scale); + } + if ((columns > 1) && (column_spacing > 0.0)) { + fprintf(fp, " 44\n%f\n", column_spacing); + } + if ((rows > 1) && (row_spacing > 0.0)) { + fprintf(fp, " 45\n%f\n", row_spacing); + } + if (rot_angle != 0.0) { + fprintf(fp, " 50\n%f\n", rot_angle); + } + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (attribute_follows != 0) { + fprintf(fp, " 66\n%d\n", attribute_follows); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } + if (columns > 1) { + fprintf(fp, " 70\n%d\n", columns); + } + if (rows > 1) { + fprintf(fp, " 71\n%d\n", rows); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_insert () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a polyline entity. + * + * Following the Polyline header is a sequence of Vertex entities that + * specify the vertex coordinates and faces that compose the mesh.\n + * Vertices such as these are described in the following subsection on + * Vertex.\n + * \n + * Applications might want to represent polygons with an arbitrarily large + * number of sides in polyface meshes.\n + * However, the AutoCAD entity structure imposes a limit on the number of + * vertices that a given face entity can specify.\n + * You can represent more complex polygons by decomposing them into triangular + * wedges.\n + */ +static void dxf_write_polyline(FILE * fp, + /*!< file pointer to output device */ + int id_code, + /*!< group code = 5 */ + char *linetype, + /*!< group code = 6 \n optional, if omitted defaults to BYLAYER */ + char *layer, + /*!< group code = 8 */ + double x0, + /*!< group code = 10 \n if omitted defaults to 0.0 */ + double y0, + /*!< group code = 20 \n if omitted defaults to 0.0 */ + double z0, + /*!< group code = 30 \n default elevation for vertices */ + double extr_x0, + /*!< group code = 210 \n extrusion direction \n optional, if ommited defaults to 0.0 */ + double extr_y0, + /*!< group code = 220 \n extrusion direction \n optional, if ommited defaults to 0.0 */ + double extr_z0, + /*!< group code = 230 \n extrusion direction \n optional, if ommited defaults to 1.0 */ + double thickness, + /*!< group code = 39 \n optional, if omitted defaults to 0.0 */ + double start_width, + /*!< group code = 40 \n optional, if omitted defaults to 0.0 */ + double end_width, + /*!< group code = 41 \n optional, if omitted defaults to 0.0 */ + int color, + /*!< group code = 62 \n optional, if omitted defaults to BYLAYER */ + int vertices_follow, + /*!< group code = 66 \n mandatory, always 1 (one or more vertices make up a polyline) */ + int paperspace, + /*!< group code = 67 \n optional, if omitted defaults to 0 (modelspace) */ + int flag, + /*!< group code = 70 \n optional, if omitted defaults to 0 */ + /*!< 1 = This is a closed Polyline (or a polygon mesh closed in the M direction) \n */ + /*!< 2 = Curve-fit vertices have been added \n */ + /*!< 4 = Spline-fit vertices have been added \n */ + /*!< 8 = This is a 3D Polyline \n */ + /*!< 16 = This is a 3D polygon mesh. \n */ + /*!< 32 = The polygon mesh is closed in the N direction \n */ + /*!< 64 = This Polyline is a polyface mesh \n */ + /*!< 128 = The linetype pattern is generated continuously around the vertices of this Polyline */ + int polygon_mesh_M_vertex_count, + /*!< group code = 71 \n optional, if omitted defaults to 0 */ + int polygon_mesh_N_vertex_count, + /*!< group code = 72 \n optional, if omitted defaults to 0 */ + int smooth_M_surface_density, + /*!< group code = 73 \n optional, if omitted defaults to 0 */ + int smooth_N_surface_density, + /*!< group code = 74 \n optional, if omitted defaults to 0 */ + int surface_type + /*!< group code = 75 \n optional, if omitted defaults to 0 \n integer coded, not bit-coded: \n */ + /*!< 0 = no smooth surface fitted \n */ + /*!< 5 = quadratic B-spline surface \n */ + /*!< 6 = cubic B-spline surface \n */ + /*!< 8 = Bezier surface \n */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_polyline () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("POLYLINE"); + if (x0 != 0.0) { + fprintf(stderr, "Warning: start point has an invalid X-value for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " %s entity is discarded from output.\n", dxf_entity_name); + return; + } + if (y0 != 0.0) { + fprintf(stderr, "Warning: start point has an invalid Y-value for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " %s entity is discarded from output.\n", dxf_entity_name); + return; + } + if (vertices_follow != 1) { + fprintf(stderr, "Warning: vertices follow flag has an invalid value for the %s entity with id-code: %x\n", dxf_entity_name, + id_code); + fprintf(stderr, " %s entity is discarded from output.\n", dxf_entity_name); + return; + } + if (strcmp(layer, "") == 0) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0\n", dxf_entity_name); + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + fprintf(fp, "100\nAcDb3dPolyline\n"); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, "210\n%f\n", extr_x0); + fprintf(fp, "220\n%f\n", extr_y0); + fprintf(fp, "230\n%f\n", extr_z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + if (start_width != 0.0) { + fprintf(fp, " 40\n%f\n", start_width); + } + if (end_width != 0.0) { + fprintf(fp, " 41\n%f\n", end_width); + } + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + fprintf(fp, " 66\n%d\n", vertices_follow); + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } + fprintf(fp, " 70\n%d\n", flag); + fprintf(fp, " 71\n%d\n", polygon_mesh_M_vertex_count); + fprintf(fp, " 72\n%d\n", polygon_mesh_N_vertex_count); + fprintf(fp, " 73\n%d\n", smooth_M_surface_density); + fprintf(fp, " 74\n%d\n", smooth_N_surface_density); + fprintf(fp, " 75\n%d\n", surface_type); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_polyline () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a section marker. + */ +static void dxf_write_section(FILE * fp, + /*!< file pointer to output device */ + char *section_name + /*!< section name */ + ) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_section () function.\n", __FILE__, __LINE__); +#endif + /* no use in writing an empty string to file */ + if (strcmp(section_name, "") == 0) { + return; + } + fprintf(fp, " 0\nSECTION\n 2\n%s\n", section_name); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_section () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a solid entity. + */ +static void dxf_write_solid(FILE * fp, + /*!< file pointer to output device */ + int id_code, + /*!< group code = 5 */ + char *linetype, + /*!< group code = 6 \n optional, defaults to BYLAYER */ + char *layer, + /*!< group code = 8 */ + double x0, + /*!< group code = 10 \n base point X-value, bottom left */ + double y0, + /*!< group code = 20 \n base point Y-value, bottom left */ + double z0, + /*!< group code = 30 \n base point Z-value, bottom left */ + double x1, + /*!< group code = 11 \n alignment point X-vaule, bottom right */ + double y1, + /*!< group code = 21 \n alignment point Y-vaule, bottom right */ + double z1, + /*!< group code = 31 \n alignment point Z-vaule, bottom right */ + double x2, + /*!< group code = 12 \n alignment point X-value, top left */ + double y2, + /*!< group code = 22 \n alignment point Y-value, top left */ + double z2, + /*!< group code = 32 \n alignment point Z-value, top left */ + double x3, + /*!< group code = 13 \n alignment point X-value, top right */ + double y3, + /*!< group code = 23 \n alignment point Y-value, top right */ + double z3, + /*!< group code = 33 \n alignment point Z-value, top right */ + double thickness, + /*!< group code = 39 \n optional, defaults to 0.0 */ + int color, + /*!< group code = 62 \n optional, defaults to BYLAYER */ + int paperspace + /*!< group code = 67 \n optional, defaults to 0 (modelspace) */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_solid () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("SOLID"); + if (strcmp(layer, "") == 0) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0", dxf_entity_name); + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + fprintf(fp, " 0\n%s\n", dxf_entity_name); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + fprintf(fp, " 11\n%f\n", x1); + fprintf(fp, " 21\n%f\n", y1); + fprintf(fp, " 31\n%f\n", z1); + fprintf(fp, " 12\n%f\n", x2); + fprintf(fp, " 22\n%f\n", y2); + fprintf(fp, " 32\n%f\n", z2); + fprintf(fp, " 13\n%f\n", x3); + fprintf(fp, " 23\n%f\n", y3); + fprintf(fp, " 33\n%f\n", z3); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_solid () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Write DXF output to a file for a polyline vertex entity. + */ +static void dxf_write_vertex(FILE * fp, + /*!< file pointer to output device */ + int id_code, + /*!< group code = 5 */ + char *linetype, + /*!< group code = 6 \n + * optional, if omitted defaults to BYLAYER */ + char *layer, + /*!< group code = 8 */ + double x0, + /*!< group code = 10 \n */ + double y0, + /*!< group code = 20 \n */ + double z0, + /*!< group code = 30 \n */ + double thickness, + /*!< group code = 39 \n + * optional, if omitted defaults to 0.0 */ + double start_width, + /*!< group code = 40 \n + * optional, if omitted defaults to 0.0 */ + double end_width, + /*!< group code = 41 \n + * optional, if omitted defaults to 0.0 */ + double bulge, + /*!< group code = 42 \n + * optional, if omitted defaults to 0.0 \n + * The bulge is the tangent of 1/4 of the included angle + * for an arc segment. \n + * Made negative if the arc goes clockwise from the start + * point to the endpoint. \n + * A bulge of 0 indicates a straight segment, and a bulge + * of 1 is a semicircle. \n */ + double curve_fit_tangent_direction, + /*!< group code = 50 \n optional, a curve-fit tangent direction of 0.0 may be omitted from the DXF output, but is significant if the flag bit is set. \n */ + int color, + /*!< group code = 62 \n optional, if omitted defaults to BYLAYER */ + int paperspace, + /*!< group code = 67 \n optional, if omitted defaults to 0 (modelspace) */ + int flag + /*!< group code = 70 \n optional, if omitted defaults to 0 + * bit coded: \n + * 1 = extra vertex created by curve-fitting \n + * 2 = curve-fit tangent defined for this vertex. \n + * 4 = unused (never set in DXF files) \n + * 8 = spline vertex created by spline-fitting \n + * 16 = spline frame control point \n + * 32 = 3D Polyline vertex \n + * 64 = 3D polygon mesh vertex \n + * 128 = polyface mesh vertex */ + ) { + char *dxf_entity_name; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_write_vertex () function.\n", __FILE__, __LINE__); + fprintf(stderr, "[DXF entity with code %x]\n", id_code); +#endif + dxf_entity_name = pcb_strdup("VERTEX"); + if (strcmp(layer, "") == 0) { + fprintf(stderr, "Warning: empty layer string for the %s entity with id-code: %x\n", dxf_entity_name, id_code); + fprintf(stderr, " %s entity is relocated to layer 0", dxf_entity_name); + layer = pcb_strdup(DXF_DEFAULT_LAYER); + } + + fprintf(fp, " 0\n%s\n", dxf_entity_name); + if (id_code != -1) { + fprintf(fp, " 5\n%x\n", id_code); + } + if (strcmp(linetype, DXF_DEFAULT_LINETYPE) != 0) { + fprintf(fp, " 6\n%s\n", linetype); + } + fprintf(fp, " 8\n%s\n", layer); + fprintf(fp, " 10\n%f\n", x0); + fprintf(fp, " 20\n%f\n", y0); + fprintf(fp, " 30\n%f\n", z0); + if (thickness != 0.0) { + fprintf(fp, " 39\n%f\n", thickness); + } + if (start_width != 0.0) { + fprintf(fp, " 40\n%f\n", start_width); + } + if (end_width != 0.0) { + fprintf(fp, " 41\n%f\n", end_width); + } + if (bulge != 0.0) { + fprintf(fp, " 42\n%f\n", bulge); + } + if (curve_fit_tangent_direction != 0.0) { + fprintf(fp, " 50\n%f\n", curve_fit_tangent_direction); + } + if (color != DXF_COLOR_BYLAYER) { + fprintf(fp, " 62\n%d\n", color); + } + if (paperspace == DXF_PAPERSPACE) { + fprintf(fp, " 67\n%d\n", DXF_PAPERSPACE); + } + fprintf(fp, " 70\n%d\n", flag); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_write_vertex () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Get export options such as filename and filename base. + * + * Returns a set of resources describing options the export or print HID + * supports.\n + * In GUI mode, the print/export dialogs use this to set up the selectable + * options.\n + * In command line mode, these are used to interpret command line options.\n + * If n_ret is non-NULL, the number of attributes is stored there. + */ +static pcb_hid_attribute_t *dxf_get_export_options(int *n) +{ + static char *last_dxf_filename; + static char *last_dxf_xref_filename; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_get_export_options () function.\n", __FILE__, __LINE__); +#endif + last_dxf_filename = 0; + last_dxf_xref_filename = 0; + if (PCB) { + pcb_derive_default_filename(PCB->Filename, &dxf_options[HA_dxffile], "", &last_dxf_filename); + pcb_derive_default_filename(PCB->Filename, &dxf_options[HA_xreffile], "", &last_dxf_xref_filename); + } + if (n) { + *n = NUM_OPTIONS; + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_get_export_options () function.\n", __FILE__, __LINE__); +#endif + return dxf_options; +} + + +/*! + * \brief Insert an element in the list of elements. + */ +static DxfList *dxf_insert(char *refdes, + /*!< reference designator. */ + char *descr, + /*!< description or footprint. */ + char *value, + /*!< element value. */ + DxfList * dxf + /*!< next item in list. */ + ) { + DxfList *new; + DxfList *cur; + DxfList *prev; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_insert () function.\n", __FILE__, __LINE__); +#endif + prev = NULL; + if (dxf == NULL) { + /* + * this is the first element so automatically create an entry. + */ + if ((new = (DxfList *) malloc(sizeof(DxfList))) == NULL) { + fprintf(stderr, "Error in dxf.c|dxf_insert (): malloc() failed.\n"); + exit(1); + } + new->next = NULL; + new->descr = pcb_strdup(descr); + new->value = pcb_strdup(value); + new->num = 1; + new->refdes = dxf_string_insert(refdes, NULL); + return (new); + } + /* + * search and see if we already have used one of these components. + */ + cur = dxf; + while (cur != NULL) { + if ((PCB_NSTRCMP(descr, cur->descr) == 0) && (PCB_NSTRCMP(value, cur->value) == 0)) { + cur->num++; + cur->refdes = dxf_string_insert(refdes, cur->refdes); + break; + } + prev = cur; + cur = cur->next; + } + if (cur == NULL) { + if ((new = (DxfList *) malloc(sizeof(DxfList))) == NULL) { + fprintf(stderr, "Error in dxf.c|dxf_insert (): malloc() failed.\n"); + exit(1); + } + prev->next = new; + new->next = NULL; + new->descr = pcb_strdup(descr); + new->value = pcb_strdup(value); + new->num = 1; + new->refdes = dxf_string_insert(refdes, NULL); + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_insert () function.\n", __FILE__, __LINE__); +#endif + return (dxf); +} + + +/*! + * \brief Print Xrefs to DXF file. + * + * Generate a file in the AutoCAD R14 DXF format for insertion of 3D models as + * external references (Xref's).\n + * An external reference is a reference to an external drawing block which is + * loaded at runtime (of the mechanical CAD software; for example AutoCAD) + * during the loading of the toplevel drawing model (the dxf file) in a + * mechanical CAD program or during separate insertions after the initial + * loading whilst in drawing mode.\n + * Note that for most mechanical CAD software the inserted block cannot be a + * DXF file.\n + * In most cases a DXF file representing a (3D) model must first be converted + * to a ".dwg" file, or any other file format native to the mechanical CAD + * software used.\n + * The filename of the 3D model inserted in the dxf file is:\n + * "parts\" + "Description or footprint name" + ".dwg" (file extension).\n + * It is assumed that the 3D models (.dwg) of the parts reside in a + * "parts" directory.\n + * All spaces in the "Description or footprint name" are palced with an + * underscore "_" resulting in the following string: + * "Description_or_footprint_name".\n + * Any element without a valid description or footprint name is inserted in the + * dxf file with a 3D model with a text "(unknown)" and this has to be + * manually inserted in the toplevel model after the initial loading of the dxf + * file.\n + * This is to prevent unnoticed ommissions of parts in the toplevel 3D model. + */ +static int dxf_export_xref_file(void) +{ + char *name; + char utcTime[64]; + double x; + double y; + double theta; + double sumx; + double sumy; + double pin1x; + double pin1y; + double pin1angle; + double pin2x; + double pin2y; + double pin2angle; + int found_pin1; + int found_pin2; + int pin_cnt; + time_t currenttime; + DxfList *dxf; + DxfList *lastb; + char *dxf_block_name; + char *dxf_xref_name; + double dxf_x0; + double dxf_y0; + double dxf_rot_angle; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_export_xref_file () function.\n", __FILE__, __LINE__); +#endif + name = NULL; + theta = 0.0; + pin1x = 0.0; + pin1y = 0.0; + pin1angle = 0.0; + pin2x = 0.0; + pin2y = 0.0; + dxf = NULL; + dxf_block_name = NULL; + dxf_xref_name = NULL; + dxf_x0 = 0.0; + dxf_y0 = 0.0; + dxf_rot_angle = 0.0; + + fp = fopen(dxf_xref_filename, "w"); + if (!fp) { + pcb_gui->log("Error in dxf.c|dxf_export_xref_file (): cannot open file %s for writing.\n", dxf_xref_filename); + return 1; + } + /* + * create a portable timestamp. + */ + currenttime = time(NULL); + strftime(utcTime, sizeof(utcTime), "%c UTC", gmtime(¤ttime)); + if (dxf_verbose) { + /* report at the beginning of each file */ + fprintf(stderr, "DXF: Board Name: %s, %s \n", PCB_UNKNOWN(PCB->Name), PCB_UNKNOWN(name)); + fprintf(stderr, "DXF: Created by: %s.\n", PCB_DXF_HID_VERSION); + fprintf(stderr, "DXF: Creation date: %s \n", utcTime); + fprintf(stderr, "DXF: File Format according to: AutoCAD R14.\n"); + if (dxf_metric) { + fprintf(stderr, "DXF using Metric coordinates [mm].\n"); + pcb_fprintf(stderr, "PCB Dimensions: %.0mm x %.0mm.\n", PCB->MaxWidth, PCB->MaxHeight); + } + else { + fprintf(stderr, "DXF using Imperial coordinates [mil].\n"); + pcb_fprintf(stderr, "PCB Dimensions: %.0mil x %.0mil.\n", PCB->MaxWidth, PCB->MaxHeight); + } + fprintf(stderr, "PCB Coordinate Origin: lower left.\n"); + fprintf(stderr, "DXF: Now processing Xrefs file.\n"); + } + /* write version info as a dxf comment */ + dxf_write_comment(fp, PCB_DXF_HID_VERSION); + /* write dxf header information */ + dxf_write_header(fp); + dxf_write_section(fp, "BLOCKS"); + /* + * lookup all elements on pcb and insert element in the list of elements. + */ + PCB_ELEMENT_LOOP(PCB->Data); + { + /* + * insert the elements into the dxf list. + */ + dxf = dxf_insert(PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element)), PCB_UNKNOWN(PCB_ELEM_NAME_VALUE(element)), dxf); + } + PCB_END_LOOP; /* End of ELEMENT_LOOP */ + /* + * now write a single block definition for every unique element to + * the BLOCKS section of the DXF file. + * since these are all supposed to be Xref blocks they are not to + * contain entities, just the path and filename (including extension). + * write a section BLOCKS marker to the DXF file. + */ + while (dxf != NULL) { + dxf_block_name = pcb_strdup(dxf_clean_string(dxf->descr)); + dxf_xref_name = DXF_DEFAULT_XREF_PATH_NAME; + dxf_write_block(fp, dxf_id_code, dxf_xref_name, dxf_block_name, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* dxf_x0, */ + 0.0, /* dxf_y0, */ + 0.0, /* dxf_z0, */ + 0.0, /* dxf_thickness, */ + DXF_COLOR_BYLAYER, /* dxf_color, */ + 0, /* dxf_paperspace, */ + 36 /* dxf_block_type */ + ); + dxf_id_code++; + lastb = dxf; + dxf = dxf->next; + free(lastb); + } + /* write an ENDSEC marker to the DXF file */ + dxf_write_endsection(fp); + /* + * write a section ENTITIES marker to the DXF file. + */ + dxf_write_section(fp, "ENTITIES"); + /* + * for each element we calculate the centroid of the footprint. + * in addition, we need to extract some notion of rotation. + */ + PCB_ELEMENT_LOOP(PCB->Data); + { + /* + * initialize our pin count and our totals for finding the + * centroid. + */ + pin_cnt = 0; + sumx = 0.0; + sumy = 0.0; + found_pin1 = 0; + found_pin2 = 0; + /* + * iterate over the pins and pads keeping a running count of + * 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++; + if (PCB_NSTRCMP(pin->Number, "1") == 0) { + pin1x = (double) pin->X; + pin1y = (double) pin->Y; + pin1angle = 0.0; + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pin->Number, "2") == 0) { + pin2x = (double) pin->X; + pin2y = (double) pin->Y; + pin2angle = 0.0; + found_pin2 = 1; + } + } + PCB_END_LOOP; /* End of PIN_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++; + if (PCB_NSTRCMP(pad->Number, "1") == 0) { + pin1x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; + pin1y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; + /* + * NOTE: we swap the Y points, because in PCB + * the Y-axis is inverted, and increasing Y + * moves down. + * we want to deal with a right-handed + * Cartesian Coordinate System where + * increasing Y moves up. + */ + pin1angle = (180.0 / M_PI) * atan2(pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pad->Number, "2") == 0) { + pin2x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; + pin2y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; + pin2angle = (180.0 / M_PI) * atan2(pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); + found_pin2 = 1; + } + } + PCB_END_LOOP; /* End of PAD_LOOP */ + if (pin_cnt > 0) { + x = sumx / (double) pin_cnt; + y = sumy / (double) pin_cnt; + if (found_pin1) { + /* + * recenter pin #1 onto the axis which cross + * at the part centroid. + */ + pin1x -= x; + pin1y -= y; + pin1y = -1.0 * pin1y; + /* if only 1 pin, use pin 1's angle */ + if (pin_cnt == 1) + theta = pin1angle; + else { + /* + * if pin #1 is at (0,0) use pin #2 for + * rotation + */ + if ((pin1x == 0.0) && (pin1y == 0.0)) { + if (found_pin2) + theta = dxf_xy_to_angle(pin2x, pin2y); + else { + pcb_message(PCB_MSG_WARNING, "dxf.c|dxf_export_xref_file ():\n" + " unable to figure out angle of element\n" + " %s because pin #1 is at the centroid of the part\n" + " and I could not find pin #2's location.\n" + " Setting to %g degrees.\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), theta); + } + } + else + theta = dxf_xy_to_angle(pin1x, pin1y); + } + } + /* we did not find pin #1 */ + else { + theta = 0.0; + pcb_message(PCB_MSG_WARNING, "dxf.c|dxf_export_xref_file ():\n" + " unable to figure out angle because I could\n" + " not find pin #1 of element %s.\n" + " Setting to %g degrees.\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), theta); + } + dxf_block_name = pcb_strdup(dxf_clean_string(PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element)))); + if (dxf_metric) { + /* convert mils to mm */ + dxf_x0 = PCB_COORD_TO_MM(x); + /* convert mils to mm and a right handed + * Cartesian Coordinate System */ + dxf_y0 = PCB_COORD_TO_MM(PCB->MaxHeight - y); + } + else { + /* + * no need to convert, some things remain the + * same. + */ + dxf_x0 = PCB_COORD_TO_MIL(x); + /* + * only convert to a right handed Cartesian + * Coordinate System. + */ + dxf_y0 = PCB_COORD_TO_MIL(PCB->MaxHeight - y); + } +#if 0 + /* + * convert the rotation angle as well: + * theta -> CW, DXF -> CCW. + */ + /*! + * \todo for now we only support Cardinal angles + * [North, East, South, West] + */ + if (theta == 0.0) + dxf_rot_angle = 90.0; + else if (theta == 90.0) + dxf_rot_angle = 0.0; + else if (theta == 180.0) + dxf_rot_angle = 270.0; + else if (theta == 270.0) + dxf_rot_angle = 180.0; + else { + dxf_rot_angle = 0.0; + pcb_message(PCB_MSG_WARNING, "dxf.c|dxf_export_xref_file ():\n" + " unable to figure out angle of dxf block\n" + " %s because pcb angle theta is not Cardinal [0.0, 90.0, 180.0, 270.0].\n" + " Setting dxf_rot_angle to %g degrees\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), dxf_rot_angle); + } +#endif + dxf_write_insert(fp, dxf_id_code, dxf_block_name, DXF_DEFAULT_LINETYPE, /* dxf_linetype, */ + DXF_DEFAULT_LAYER, /* dxf_layer, */ + dxf_x0, dxf_y0, 0.0, /* dxf_z0, */ + 0.0, /* dxf_thickness, */ + 1.0, /* dxf_rel_x_scale, */ + 1.0, /* dxf_rel_y_scale, */ + 1.0, /* dxf_rel_z_scale, */ + 0.0, /* dxf_column_spacing, */ + 0.0, /* dxf_row_spacing, */ + dxf_rot_angle, DXF_COLOR_BYLAYER, /* dxf_color, */ + 0, /* dxf_attribute_follows, */ + 0, /* dxf_paperspace, */ + 1, /* dxf_columns, */ + 1 /* dxf_rows */ + ); + } + dxf_id_code++; + } + PCB_END_LOOP; /* End of ELEMENT_LOOP */ + /* + * write an ENDSEC marker to the DXF file. + */ + dxf_write_endsection(fp); + /* + * write an EOF marker and close the DXF file. + */ + dxf_write_eof(fp); + fclose(fp); + fp = NULL; + dxf_id_code = 0; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_export_xref_file () function.\n", __FILE__, __LINE__); +#endif + return (0); +} + + +/*! + * \brief Close DXF layer file. + */ +static void dxf_maybe_close_file() +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_maybe_close_file () function.\n", __FILE__, __LINE__); +#endif + if (fp) { + /* write an EOF marker and close the DXF file */ + dxf_write_eof(fp); + fclose(fp); + } + dxf_id_code = 0; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_maybe_close_file () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Export (or print) the current PCB. + * + * The options given represent the choices made from the options returned + * from dxf_get_export_options.\n + * Call with options == NULL to start the primary GUI (create a main window, + * print, export, etc).\n + * \n + * First get the export options.\n + * Do export all the DXF files required.\n + *
      + *
    • Export the DXF file with Xref blocks to a seperate dxf file if required.\n + *
    • Export a DXF file for every PCB layer.\n + *
    + */ +static void dxf_do_export(pcb_hid_attr_val_t * options) +{ + const char *dxf_fnbase; + int i; + static int saved_layer_stack[PCB_MAX_LAYER]; + pcb_hid_expose_ctx_t ctx; + int save_ons[PCB_MAX_LAYER + 2]; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_do_export () function.\n", __FILE__, __LINE__); +#endif + dxf_fnbase = NULL; + + if (!options) { + dxf_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) { + dxf_values[i] = dxf_options[i].default_val; + } + options = dxf_values; + } + /* + * verbose output (dxf files to contain comments). + */ + dxf_verbose = options[HA_verbose].int_value; + /* + * if all layers needs to be exported. + */ + dxf_export_all_layers = options[HA_export_all_layers].int_value; + /* + * output to be in in mils or mm. + */ + dxf_metric = options[HA_metric].int_value; + /* + * entity color to be BYBLOCK (or by layer number). + */ + dxf_color_is_byblock = options[HA_color_byblock].int_value; + /* + * if xrefs DXF file needs to be exported. + */ + dxf_xrefs = options[HA_xrefs].int_value; + if (dxf_xrefs) { + const char *xreff; + /* + * determine a file name for the xref file. + */ + xreff = options[HA_xreffile].str_value; + if (xreff == NULL) + xreff = "pcb-out_xrefs"; + i = strlen(xreff); + dxf_xref_filename = (char *) realloc(dxf_xref_filename, i + 40); + memcpy(dxf_xref_filename, xreff, i+1); + strcat(dxf_xref_filename, "_xrefs.dxf"); + dxf_filesuffix = dxf_xref_filename + strlen(dxf_xref_filename); + dxf_export_xref_file(); + } + /* + * determine a file name base for the DXF layer files. + */ + dxf_fnbase = options[HA_dxffile].str_value; + if (!dxf_fnbase) { + dxf_fnbase = "pcb_layers"; + } + i = strlen(dxf_fnbase); + dxf_filename = (char *) realloc(dxf_filename, i + 40); + strcpy(dxf_filename, dxf_fnbase); + strcat(dxf_filename, "_"); + dxf_filesuffix = dxf_filename + strlen(dxf_filename); + /* + * use this to temporarily enable all layers. + */ + 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]), dxf_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; +/* dxf_init_apertures ();*/ + lastgroup = -1; + c_layerapps = 0; + dxf_finding_apertures = 1; + pcb_hid_expose_all(&dxf_hid, &ctx); + c_layerapps = 0; + dxf_finding_apertures = 0; + pcb_hid_expose_all(&dxf_hid, &ctx); + memcpy(pcb_layer_stack, saved_layer_stack, sizeof(pcb_layer_stack)); + dxf_maybe_close_file(); + pcb_hid_restore_layer_ons(save_ons); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_do_export () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Parse the command line. + * + * Parse HID register attributes and HID command line arguments.\n + * Call this early for whatever HID will be the primary HID, as it will set + * all the registered attributes.\n + * The HID should remove all arguments, leaving any possible file names + * behind. + */ +static void dxf_parse_arguments(int *argc, char ***argv) +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_parse_arguments () function.\n", __FILE__, __LINE__); +#endif + pcb_hid_parse_command_line(argc, argv); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_parse_arguments () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Sort drills (holes). + */ +static int dxf_drill_sort(const void *va, const void *vb) { + DxfPendingDrills *a; + DxfPendingDrills *b; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_drill_sort () function.\n", __FILE__, __LINE__); +#endif + a = (DxfPendingDrills *) va; + b = (DxfPendingDrills *) vb; + if (a->diam != b->diam) + return a->diam - b->diam; + if (a->x != b->x) + return a->x - a->x; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_drill_sort () function.\n", __FILE__, __LINE__); +#endif + return b->y - b->y; +} + + +/*! + * \brief Set the layer with name for DXF export. + * + * During redraw or print/export cycles, this is called once per layer + * (or layer group, for copper layers).\n + * If it returns false (zero), the HID does not want that layer, and none of + * the drawing functions should be called.\n + * If it returns true (nonzero), the items in that layer [group] should be + * drawn using the various drawing functions.\n + * For copper layer groups, you may pass NULL for name to have a name fetched + * from the PCB struct.\n + * \n + * All copper containing layers are set for DXF export.\n + * All assembly layers are set for DXF export.\n + * Exceptions are: \n + *
      + *
    • Layers with the name "invisible" are not set for DXF export. + *
    • Layers with the name "keepout" are not set for DXF export. + *
    • Layers without exportable items are not set for DXF export. + *
    + */ +static int dxf_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + char *cp; + const char *fmt; + char tmp_ln[PCB_PATH_MAX]; + const char *name = pcb_layer_to_file_name(tmp_ln, layer, flags, PCB_FNS_fixed); + + if (flags & PCB_LYT_UI) + return 0; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_set_layer () function.\n", __FILE__, __LINE__); +#endif + + if (dxf_verbose) { + fprintf(stderr, "DXF: now processing Layer group %ld, flags %x\n", group, flags); + } + if (dxf_export_all_layers) { + /* do nothing here to export all layers */ + } + else { + if (pcb_layergrp_is_empty(PCB, group)) { + /* do not export empty layers */ + if (dxf_verbose) { + fprintf(stderr, "DXF: Warning, Layer %ld contains no exportable items and is not set.\n", group); + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_layer () function.\n", __FILE__, __LINE__); + } + return 0; + } + if (flags & PCB_LYT_INVIS) { + /* do not export the layer with the name "invisible" */ + if (dxf_verbose) { + fprintf(stderr, "DXF: Warning, Layer %ld not set.\n", group); + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_layer () function.\n", __FILE__, __LINE__); + } + return 0; + } +#if 0 + if (flags & PCB_LYT_KEEPOUT) { + /* do not export the layer with the name "keepout" */ + if (dxf_verbose) { + fprintf(stderr, "DXF: Warning, Layer %s not set.\n", name); + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_layer () function.\n", __FILE__, __LINE__); + } + return 0; + } +#endif + if (flags & PCB_LYT_ASSY) { + /* do not export the layers with the type ASSY */ + if (dxf_verbose) { + fprintf(stderr, "DXF: Warning, Layer %ld with type ASSY not set.\n", group); + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_layer () function.\n", __FILE__, __LINE__); + } + return 0; + } + } + + is_drill = ((flags & PCB_LYT_PDRILL) || (flags & PCB_LYT_UDRILL)); + is_mask = !!(flags & PCB_LYT_MASK); + + if (is_drill && dxf_n_pending_drills) { + int i; + /* dump pending drills in sequence */ + qsort(dxf_pending_drills, dxf_n_pending_drills, sizeof(DxfPendingDrills), dxf_drill_sort); + for (i = 0; i < dxf_n_pending_drills; i++) { + if (i == 0 || dxf_pending_drills[i].diam != dxf_pending_drills[i - 1].diam) { + if (dxf_verbose) { + /*! + * \todo this output should go to file in + * whatever form instead of being put on stderr. + */ +/* fprintf (stderr, + "DXF: T%02d\015\012", ap);*/ + } + } + if (dxf_verbose) { + /*! + * \todo this output should go to file in + * whatever form instead of being put on stderr. + */ + fprintf(stderr, "DXF: X:%06d Y:%06d\n", DXF_X(PCB, dxf_pending_drills[i].x), DXF_Y(PCB, dxf_pending_drills[i].y)); + } + } + free(dxf_pending_drills); + dxf_n_pending_drills = dxf_max_pending_drills = 0; + dxf_pending_drills = 0; + } + current_mask = 0; + if (group < 0 || group != lastgroup) { + time_t currenttime; + char utcTime[64]; + char *sext = "_layer.dxf"; + lastgroup = group; + dxf_lastX = -1; + dxf_lastY = -1; + lastcolor = 0; + linewidth = -1; + lastcap = -1; +/* dxf_set_app_layer (c_layerapps);*/ + c_layerapps++; + if (dxf_finding_apertures) { + return 1; + } +/* if (!curapp->nextAperture) + { + return 0; + }*/ + dxf_maybe_close_file(); + pagecount++; + if (is_drill) + sext = ".dxf"; + strcpy(dxf_filesuffix, name); + strcat(dxf_filesuffix, sext); +printf("SET LAYER: %s\n", dxf_filename); + fp = fopen(dxf_filename, "w"); + if (fp == NULL) { + pcb_message(PCB_MSG_ERROR, "DXF: could not open %s for writing.\n", dxf_filename); + return 1; + } + /* write version info as a dxf comment */ + dxf_write_comment(fp, PCB_DXF_HID_VERSION); + /* write dxf header information */ + dxf_write_header(); + /* write a section ENTITIES marker to the DXF file */ + dxf_write_section(fp, "ENTITIES"); + was_drill = is_drill; + /*! + * \todo this output should go to file in + * whatever form instead of being put on stderr. + */ + if (dxf_verbose) { + fprintf(stderr, "DXF: Start of page %d for group %ld flags %x\n", pagecount, group, flags); + } + if (group < 0 || group != lastgroup) { + /* create a portable timestamp */ + currenttime = time(NULL); + /* avoid gcc complaints */ + fmt = pcb_strdup("%c UTC"); + strftime(utcTime, sizeof utcTime, fmt, gmtime(¤ttime)); + } + if (dxf_verbose) { + /* report at the beginning of each file */ + fprintf(stderr, "DXF: Board Name: %s, %s \n", PCB_UNKNOWN(PCB->Name), PCB_UNKNOWN(name)); + fprintf(stderr, "DXF: Created by: %s.\n", PCB_DXF_HID_VERSION); + fprintf(stderr, "DXF: Creation date: %s \n", utcTime); + fprintf(stderr, "DXF: File Format according to: AutoCAD R14.\n"); + if (dxf_metric) { + fprintf(stderr, "DXF using Metric coordinates [mm].\n"); + pcb_fprintf(stderr, "PCB Dimensions: %.0mm x %.0mm.\n", PCB->MaxWidth, PCB->MaxHeight); + } + else { + fprintf(stderr, "DXF using Imperial coordinates [mil].\n"); + pcb_fprintf(stderr, "PCB Dimensions: %.0ml x %.0ml.\n", PCB->MaxWidth, PCB->MaxHeight); + } + fprintf(stderr, "PCB Coordinate Origin: lower left.\n"); + fprintf(stderr, "DXF: Now processing Layer %s group %ld drill %d mask %d\n", name, group, is_drill, is_mask); + } + /* build a legal identifier */ + if (dxf_layername) { + free(dxf_layername); + } + dxf_layername = pcb_strdup(dxf_filesuffix); + dxf_layername[strlen(dxf_layername) - strlen(sext)] = 0; + /* remove all non-alpha-nummerical characters and change all to upper characters */ + for (cp = dxf_layername; *cp; cp++) { + if (isalnum((int) *cp)) { + *cp = toupper(*cp); + } + else { + *cp = '_'; + } + } + lncount = 1; + if (dxf_verbose) { + fprintf(stderr, "DXF: Setting Layer %s.\n", dxf_layername); +/* fprintf (stderr, "DXF: Aperture Data %s.\n", curapp->appList.Data);*/ + } + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_layer () function.\n", __FILE__, __LINE__); +#endif + return 1; +} + + +/*! + * \brief Constructor for the graphic context. + */ +static pcb_hid_gc_t dxf_make_gc(void) +{ + pcb_hid_gc_t rv; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_make_gc () function.\n", __FILE__, __LINE__); +#endif + rv = (pcb_hid_gc_t) calloc(1, sizeof(hid_gc_s)); + rv->cap = Trace_Cap; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_make_gc () function.\n", __FILE__, __LINE__); +#endif + return rv; +} + + +/*! + * \brief Destructor for the graphic context. + */ +static void dxf_destroy_gc(pcb_hid_gc_t gc) +{ +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_destroy_gc () function.\n", __FILE__, __LINE__); +#endif + free(gc); +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_destroy_gc () function.\n", __FILE__, __LINE__); +#endif +} + +/*! + * Special note about the "erase" color: To use this color, you must use this + * function to tell the HID when you're using it.\n + * At the beginning of a layer redraw cycle (i.e. after set_layer), call + * use_mask() to redirect output to a buffer.\n + * Draw to the buffer (using regular HID calls) using regular and "erase" + * colors.\n + * Then call use_mask(HID_MASK_OFF) to flush the buffer to the HID.\n + * If you use the "erase" color when use_mask is disabled, it simply draws in + * the background color.\n + * Values:\n + *
      + *
    • HID_MASK_OFF == 0 Flush the buffer and return to non-mask operation. + *
    • HID_MASK_BEFORE == 1 Polygons being drawn before clears. + *
    • HID_MASK_CLEAR == 2 Clearances being drawn. + *
    • HID_MASK_AFTER == 3 Polygons being drawn after clears. + *
    + */ +static void dxf_use_mask(pcb_mask_op_t use_it) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_use_mask () function.\n", __FILE__, __LINE__); +#endif + current_mask = use_it; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_use_mask () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Set a color. + * + * Set the color of the entity. + * 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.\n + * Always use the "drill" color to draw holes.\n + * You may assume this is cheap enough to call inside the redraw callback, + * but not cheap enough to call for each item drawn. + */ +static void dxf_set_color(pcb_hid_gc_t gc, /*!< graphic context */ + const char *name) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_set_color () function.\n", __FILE__, __LINE__); +#endif + 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; + } +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_color () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Set the line style. + * + * Set the line cap style in the graphic context.\n + * While calling this is cheap, calling it with different values each time + * may be expensive, so grouping items by line style is helpful. +*/ +static void dxf_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_set_line_cap () function.\n", __FILE__, __LINE__); +#endif + gc->cap = style; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_line_cap () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Set the line width. + * + * Set the line width in the graphic context.\n + * While calling this is cheap, calling it with different values each time + * may be expensive, so grouping items by line width is helpful. + */ +static void dxf_set_line_width(pcb_hid_gc_t gc, int width) { +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_set_line_width () function.\n", __FILE__, __LINE__); +#endif + gc->width = width; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_set_line_width () function.\n", __FILE__, __LINE__); +#endif +} + + +static void dxf_set_draw_xor(pcb_hid_gc_t gc, int xor_) +{ + ; +} + + +/*! + * \brief Use the graphic context. + */ +static void dxf_use_gc(pcb_hid_gc_t gc, int radius) { + int c; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_use_gc () function.\n", __FILE__, __LINE__); +#endif + if (radius) { + radius *= 2; + if (radius != linewidth || lastcap != Round_Cap) { +/* c = dxf_find_aperture_code (radius, ROUND);*/ + if (c <= 0) { + fprintf(stderr, "DXF: Error, aperture for radius %d type ROUND is %d\n", radius, c); + } + if (fp && !is_drill) { + fprintf(stderr, "DXF: is not a drill %d.\n", c); + } + linewidth = radius; + lastcap = Round_Cap; + } + } + else if (linewidth != gc->width || lastcap != gc->cap) { + linewidth = gc->width; + lastcap = gc->cap; + switch (gc->cap) { + case Round_Cap: + case Trace_Cap: + c = SHP_ROUND; + break; + default: + case Square_Cap: + c = SHP_SQUARE; + break; + } + if (fp) { +/* fprintf (stderr, "DXF: aperture %d.\n ", ap); */ + } + } +#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 (fp) { + if (c) { + /*! + * \todo this output should go to file in + * whatever form instead of being put on stderr. + */ + fprintf(stderr, "%%LN%s_C%d*%%\015\012", layername, lncount++); + fprintf(stderr, "%%LPC*%%\015\012"); + } + else { + fprintf(stderr, "%%LN%s_D%d*%%\015\012", layername, lncount++); + fprintf(stderr, "%%LPD*%%\015\012"); + } + } + } +#endif +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leavinging dxf_use_gc () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw a rectangle. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + * We draw the rectangle counter clockwise (CCW) with 5 vertices + * (XY-coordinates).\n + * It is assumed that the first XY-coordinate pair (x1, y1) contains the + * bottom left corner values and that the second XY-coordinate pair (x2, y2) + * contains the top right corner values. \n + * The rectangle is not filled, use dxf_fill_rect () for a filled rectangle. + */ +static void dxf_draw_rect(pcb_hid_gc_t gc, + /*!< graphic context */ + int x1, + /*!< X-value bottom left ?? point */ + int y1, + /*!< Y-value bottom left ?? point */ + int x2, + /*!< X-value top right ?? point */ + int y2 + /*!< Y-value top right ?? point */ + ) { + double dxf_start_width; + double dxf_end_width; + int dxf_color; + double dxf_x0; + double dxf_y0; + double dxf_x1; + double dxf_y1; + double dxf_x2; + double dxf_y2; + double dxf_x3; + double dxf_y3; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_draw_rect () function.\n", __FILE__, __LINE__); +#endif + /* + * return if no valid file pointer exists. + */ + if (!fp) { + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + if ((x1 == x2) && (y1 == y2)) { + fprintf(stderr, "Warning: start point and end point are identical for the entity with id-code: %x\n", dxf_id_code); + fprintf(stderr, " entity is discarded from output.\n"); + return; + } + dxf_start_width = (double) gc->width; + dxf_end_width = (double) gc->width; + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + dxf_x0 = DXF_X(PCB, x1); + dxf_y0 = DXF_Y(PCB, y1); + dxf_x1 = DXF_X(PCB, x2); + dxf_y1 = DXF_Y(PCB, y1); + dxf_x2 = DXF_X(PCB, x1); + dxf_y2 = DXF_Y(PCB, y2); + dxf_x3 = DXF_X(PCB, x2); + dxf_y3 = DXF_Y(PCB, y2); + /* + * write polyline sequence. + */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, *//* the polyline entity always remains on 0.0, 0.0, 0.0 */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, *//* the polyline extrusion vector always is 0.0, 0.0, 1.0 */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 0, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* + * write first XY-coordinate (base point, bottom left corner). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write second XY-coordinate (bottom right corner). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x1, dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write third XY-coordinate (top right left corner). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x1, dxf_y1, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write fourth XY-coordinate (top left corner). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y1, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write fifth XY-coordinate (again the bottom left corner, to close + * the rectangle). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * end of polyline sequence. + */ + dxf_write_endseq(fp); + dxf_lastX = dxf_x1; + dxf_lastY = dxf_y1; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_draw_rect () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw a line. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + * Translate the pcb X,Y-coordinates of lines and trace segments to dxf + * X,Y,Z-coordinates.\n + * Add layer, linetype, color and width values.\n + * Write a series of polylines and vertices by calling low level functions.\n + * If the endcap style is SHP_ROUND add a donut at the begin and end coordinates + * of the line segment.\n + * If the endcap style is SHP_SQUARE elongate the line segment with half its + * width.\n + * Remarks:\n + *
      + *
    • We do not draw lines of 1 mil wide or smaller.\n + *
    • We do not draw lines with identical start and end XY-coordinates (zero + * length).\n + *
    • We draw every trace segment as a single AutoCAD entity (polyline).\n + *
    + * + * \todo In case of a series of trace segments, we have to continue with a + * vertex from the last XY-coordinates.\n + * While the conditions for starting or continuing are simple to determine:\n + * if ((dxf_x1, dxf_y1) == dxf_lastX, dxf_lastY)) ... \n + * The caveat is how to determine when to close the polyline sequence + * (with an ENDSEQ marker) after the last vertex (endpoint of the last trace + * segment).\n + * One approach could be to close the series when the start coordinates of the + * new (to be drawn) trace segment do not coincide with the endpoint of the + * previously used trace segment (dxf_last[X. Y] values).\n + * This however would not be a solution for a branching trace segment or the + * last trace segment to be drawn on that particular layer.\n + * For the last trace segment to be drawn on a particular layer, we would have + * to check if the layer didn't change since the last trace segment was + * drawn.\n + */ +static void dxf_draw_line(pcb_hid_gc_t gc, + /*!< graphic context */ + int x1, + /*!< X-value start point */ + int y1, + /*!< Y-value start point */ + int x2, + /*!< X-value end point */ + int y2 + /*!< Y-value end point */ + ) { + pcb_bool m; + double dxf_x0; /* start point */ + double dxf_y0; /* start point */ + double dxf_x1; /* end point */ + double dxf_y1; /* end point */ + double dxf_start_width; /* trace width */ + double dxf_end_width; /* trace width */ + int dxf_color; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_draw_line () function.\n", __FILE__, __LINE__); +#endif + m = pcb_false; + if (!fp) { + /* return if no valid file pointer exists */ + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + if (gc->width == 1) { + /* we do not draw 1 mil width traces */ + fprintf(stderr, "Warning: lines with a width == 1 mil will not be drawn.\n"); + fprintf(stderr, " entity is discarded from output.\n"); + return; + } + if ((x1 == x2) && (y1 == y2)) { + /* we do not draw zero length traces */ + fprintf(stderr, "Warning: start point and end point are identical for the entity with id-code: %x.\n", dxf_id_code); + fprintf(stderr, " entity is discarded from output.\n"); + return; + } + dxf_use_gc(gc, 0); + /* determine the polyline widths */ + if (dxf_metric) { + dxf_start_width = (double) PCB_COORD_TO_MM(gc->width); + dxf_end_width = (double) PCB_COORD_TO_MM(gc->width); + } + else { + dxf_start_width = (double) PCB_COORD_TO_MIL(gc->width); + dxf_end_width = (double) PCB_COORD_TO_MIL(gc->width); + } + /* determine polyline color */ + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + /* + * determine start and end point X,Y-values w.r.t. metric or imperial. + */ + if (dxf_metric) { + dxf_x0 = PCB_COORD_TO_MM(DXF_X(PCB, x1)); + dxf_y0 = PCB_COORD_TO_MM(DXF_Y(PCB, y1)); + dxf_x1 = PCB_COORD_TO_MM(DXF_X(PCB, x2)); + dxf_y1 = PCB_COORD_TO_MM(DXF_Y(PCB, y2)); + } + else { + dxf_x0 = PCB_COORD_TO_MIL(DXF_X(PCB, x1)); + dxf_y0 = PCB_COORD_TO_MIL(DXF_Y(PCB, y1)); + dxf_x1 = PCB_COORD_TO_MIL(DXF_X(PCB, x2)); + dxf_y1 = PCB_COORD_TO_MIL(DXF_Y(PCB, y2)); + } + /*! + * \todo Someday we have to do something here with multiple trace + * segments here, the problem for now is how to determine when the + * last trace segment was passed. + */ + if ((dxf_x0 == dxf_lastX) && (dxf_y0 == dxf_lastY)) { + m = pcb_true; + } + /* + * This is just a dirty hack for AutoCAD doesn't have endcap styles. + * Donuts can not be implementend in the trace polyline since donuts + * are a closed polyline themselves. + */ + if (gc->cap == SHP_ROUND) { + /* place a donut at the start of the trace segment */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 1, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* + * write first XY-coordinate (at the start of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0 - (0.25 * dxf_start_width), dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write second XY-coordinate (at the start of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0 + (0.25 * dxf_start_width), dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* write the end of polyline sequence marker */ + dxf_write_endseq(fp); + /* place a donut at the end of the trace segment */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 1, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* + * write first XY-coordinate (at the end of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x1 - (0.25 * dxf_start_width), dxf_y1, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write second XY-coordinate (at the end of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x1 + (0.25 * dxf_start_width), dxf_y1, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write the end of polyline sequence marker. + */ + dxf_write_endseq(fp); + } + /* if the end cap style is an OCTAGON: ?? */ + if (gc->cap == SHP_OCTAGON) { + /*! + * \todo This end cap style has yet to be implemented at the + * start and end point of a trace. + * Note: done for SHP_ROUND and SQUARE. + */ + } + /* + * if the end cap style is SQUARE: recompute the start and end + * coordinates, that is, elongate the trace with half of the width. + */ + if (gc->cap == SHP_SQUARE) { + double length; /* trace length */ + double dxf_x0_1; /* extended start point */ + double dxf_y0_1; /* extended start point */ + double dxf_x1_1; /* extended end point */ + double dxf_y1_1; /* extended end point */ + length = sqrt((dxf_y1 - dxf_y0) * (dxf_y1 - dxf_y0) + (dxf_x1 - dxf_x0) * (dxf_x1 - dxf_x0)); + dxf_x0_1 = dxf_x0 - ((dxf_x1 - dxf_x0) / length) * 0.5 * dxf_start_width; + dxf_y0_1 = dxf_y0 - ((dxf_y1 - dxf_y0) / length) * 0.5 * dxf_start_width; + dxf_x1_1 = dxf_x1 + ((dxf_x1 - dxf_x0) / length) * 0.5 * dxf_end_width; + dxf_y1_1 = dxf_y1 + ((dxf_y1 - dxf_y0) / length) * 0.5 * dxf_end_width; + dxf_x0 = dxf_x0_1; + dxf_y0 = dxf_y0_1; + dxf_x1 = dxf_x1_1; + dxf_y1 = dxf_y1_1; + } + /* write polyline sequence for the trace */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 0, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* write first XY-coordinate (start of trace segment) */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* write second XY-coordinate (end of trace segment) */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x1, dxf_y1, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_start_width, dxf_end_width, 0.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* write the end of polyline sequence marker */ + dxf_write_endseq(fp); + dxf_lastX = dxf_x1; + dxf_lastY = dxf_y1; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_draw_line () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw an (elliptic ?) arc. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + * For now we draw an (elliptic) arc with the assumption that the width is + * along the X-axis and the height is along the Y-axis.\n + * Thus the major axis of the ellipse has a size of 2 * the maximum of the + * greatest value of [width, height], and the minor axis has a size of 2 * the + * minimum value of [width, height].\n + * An elliptic arc with a line width of 0 is implemented for now. + * + * \todo The elliptic arc entity has to be replaced by a polyline with the + * correct line width (trace width). + * \todo In the case of a series of trace segments, continue with a vertex + * from the last XY-coordinates.\n + * While the conditions for starting or continuing are simple to determine:\n + * if ((x1, y1) == dxf_lastX, dxf_lastY)) ... \n + * The caveat is how to determine when to close the polyline sequence (with + * an ENDSEQ marker) after the last vertex (endpoint of the last trace + * segment).\n + * \todo The end cap style has to be implemented at the start and end point of + * a trace. + */ +static void dxf_draw_arc(pcb_hid_gc_t gc, + /*!< graphic context */ + int cx, + /*!< X-value center point */ + int cy, + /*!< X-value center point */ + int width, + /*!< length of major axis */ + int height, + /*!< length of minor axis */ + int start_angle, + /*!< start angle of elliptic arc */ + int delta_angle + /*!< relative angle to end angle */ + ) { + float arcStartX; + float arcStopX; + float arcStartY; + float arcStopY; + double dxf_x0; /* center point */ + double dxf_y0; /* center point */ + double dxf_x1; /* end point major axis */ + double dxf_y1; /* end point major axis */ + double dxf_arcstart_x; + double dxf_arcstart_y; + double dxf_arcstop_x; + double dxf_arcstop_y; + double dxf_start_width; /* trace width */ + double dxf_end_width; /* trace width */ + double dxf_width; /* arc width */ + double dxf_height; /* arc height */ + double dxf_ratio; + double dxf_start_angle; + double dxf_end_angle; + int dxf_color; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_draw_arc () function.\n", __FILE__, __LINE__); +#endif +#if 0 + pcb_bool m = pcb_false; +#endif + if (!fp) { + /* return if no valid file pointer exists */ + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + if (gc->width == 0) { + /* we do not draw 0 mil wide traces */ + fprintf(stderr, "Warning: arcs with a width == 0 mil will not be drawn.\n"); + fprintf(stderr, " entity is discarded from output.\n"); + return; + } + dxf_use_gc(gc, 0); + arcStartX = cx - width * cos(PCB_TO_RADIANS(start_angle)); + arcStartY = cy + height * sin(PCB_TO_RADIANS(start_angle)); + arcStopX = cx - width * cos(PCB_TO_RADIANS(start_angle + delta_angle)); + arcStopY = cy + height * sin(PCB_TO_RADIANS(start_angle + delta_angle)); + if (dxf_metric) { + /* use metric (mm) */ + dxf_x0 = PCB_COORD_TO_MM(DXF_X(PCB, cx)); + dxf_y0 = PCB_COORD_TO_MM(DXF_Y(PCB, cy)); + dxf_start_width = PCB_COORD_TO_MM(DXF_X(PCB, width)); + dxf_end_width = PCB_COORD_TO_MM(DXF_X(PCB, width)); + dxf_height = PCB_COORD_TO_MM(DXF_X(PCB, height)); + dxf_width = PCB_COORD_TO_MM(DXF_X(PCB, width)); + if (dxf_width > dxf_height) { + /* + * the major axis of the ellipse coincides with the + * X-axis. + */ + dxf_x1 = PCB_COORD_TO_MM(DXF_X(PCB, (cx + width))); + dxf_y1 = PCB_COORD_TO_MM(DXF_Y(PCB, cy)); + /* + * the dxf_ratio is the minor axis length over major + * axis length, and is always <= 1.0 + */ + dxf_ratio = dxf_height / dxf_width; + } + else { + /* + * the major axis of the ellipse coincides with the + * Y-axis. + */ + dxf_x1 = PCB_COORD_TO_MM(DXF_X(PCB, cx)); + dxf_y1 = PCB_COORD_TO_MM(DXF_Y(PCB, (cy + height))); + /* + * the dxf_ratio is the minor axis length over major + * axis length, and is always <= 1.0 + */ + dxf_ratio = dxf_width / dxf_height; + } + } + else { + /* use imperial (mil) */ + dxf_x0 = PCB_COORD_TO_MIL(DXF_X(PCB, cx)); + dxf_y0 = PCB_COORD_TO_MIL(DXF_Y(PCB, cy)); + dxf_start_width = PCB_COORD_TO_MIL(DXF_X(PCB, width)); + dxf_end_width = PCB_COORD_TO_MIL(DXF_X(PCB, width)); + dxf_height = PCB_COORD_TO_MIL(DXF_Y(PCB, height)); + dxf_width = PCB_COORD_TO_MIL(DXF_Y(PCB, width)); + if (dxf_width > dxf_height) { + /* + * the major axis of the ellipse coincides with the + * X-axis. + */ + dxf_x1 = DXF_X(PCB, (cx + width)); + dxf_y1 = DXF_Y(PCB, cy); + /* + * the dxf_ratio is the minor axis length over major + * axis length, and is always <= 1.0 + */ + dxf_ratio = dxf_height / dxf_width; + } + else { + /* + * the major axis of the ellipse coincides with the + * Y-axis. + */ + dxf_x1 = DXF_X(PCB, cx); + dxf_y1 = DXF_Y(PCB, (cy + height)); + /* + * the dxf_ratio is the minor axis length over major + * axis length, and is always <= 1.0 + */ + dxf_ratio = dxf_width / dxf_height; + } + } + /* + * we have to add 180 degrees for start_angle and end_angle because + * in the pcb universe 0 degrees (the negative X-axis) is to the left, + * and in the dxf universe 0 degrees is to the right. + */ + dxf_start_angle = PCB_TO_RADIANS(start_angle + 180); + dxf_end_angle = PCB_TO_RADIANS(start_angle + delta_angle + 180); + if (dxf_start_angle >= (2 * M_PI)) { + dxf_start_angle = dxf_start_angle - (2 * M_PI); + } + if (dxf_end_angle >= (2 * M_PI)) { + dxf_end_angle = dxf_end_angle - (2 * M_PI); + } + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + dxf_arcstart_x = DXF_X(PCB, arcStartX); + dxf_arcstart_y = DXF_Y(PCB, arcStartY); + dxf_arcstop_x = DXF_X(PCB, arcStopX); + dxf_arcstop_y = DXF_Y(PCB, arcStopY); + /* + * This is just a dirty hack for AutoCAD doesn't have endcap styles. + * Donuts can not be implemented in the trace polyline since donuts + * are a closed polyline themselves. + */ + if (gc->cap == SHP_ROUND) { + /* place a donut at the start of the trace segment */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 1, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* + * write first XY-coordinate (at the start of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_arcstart_x - (0.25 * dxf_start_width), dxf_arcstart_y, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write second XY-coordinate (at the start of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_arcstart_x + (0.25 * dxf_start_width), dxf_arcstart_y, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write the end of polyline sequence marker. + */ + dxf_write_endseq(fp); + /* + * place a donut at the end of the trace segment. + */ + dxf_write_polyline(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + 0.0, /* x0, */ + 0.0, /* y0, */ + 0.0, /* z0, */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, dxf_color, /* color, */ + 1, /* vertices_follow, */ + 0, /* modelspace, */ + 1, /* flag, */ + 0, /* polygon_mesh_M_vertex_count, */ + 0, /* polygon_mesh_N_vertex_count, */ + 0, /* smooth_M_surface_density, */ + 0, /* smooth_N_surface_density, */ + 0 /* surface_type */ + ); + dxf_id_code++; + /* + * write first XY-coordinate (at the end of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_arcstop_x - (0.25 * dxf_start_width), dxf_arcstop_y, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write second XY-coordinate (at the end of trace segment). + */ + dxf_write_vertex(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_arcstop_x + (0.25 * dxf_start_width), dxf_arcstop_y, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* thickness, *//* copper weight ?? */ + 0.5 * dxf_start_width, 0.5 * dxf_end_width, 1.0, /* bulge, */ + 0.0, /* curve_fit_tangent_direction, */ + dxf_color, 0, /* modelspace, */ + 0 /* flag */ + ); + dxf_id_code++; + /* + * write the end of polyline sequence marker. + */ + dxf_write_endseq(fp); + } + /* + * write an ellipse for the trace. + */ + dxf_write_ellipse(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, */ + dxf_x1, dxf_y1, 0.0, /* z1, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* dxf_extr_x0, */ + 0.0, /* dxf_extr_y0, */ + 1.0, /* dxf_extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_ratio, dxf_start_angle, dxf_end_angle, dxf_color, 0 /* modelspace */ + ); + dxf_id_code++; + dxf_lastX = arcStopX; + dxf_lastY = arcStopY; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_draw_arc () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw a filled circle. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + * \todo Implement a donut (polyline) instead of a circle. + */ +static void dxf_fill_circle(pcb_hid_gc_t gc, + /*!< graphic context. */ + int cx, + /*!< X-value center point. */ + int cy, + /*!< Y-value center point. */ + int radius + /*!< radius of circle. */ + ) { + double dxf_x0; + double dxf_y0; + double dxf_radius; + int dxf_color; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_fill_circle () function.\n", __FILE__, __LINE__); +#endif + /* + * return if no valid file pointer exists. + */ + if (!fp) { + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + /* + * drill sizes increase per 2 mil ? + */ + if (is_drill) { + radius = DXF_ROUND(radius * 2) / 2; + } + dxf_use_gc(gc, radius); + if (is_drill) { + if (dxf_n_pending_drills >= dxf_max_pending_drills) { + dxf_max_pending_drills += 100; + /* + * re-allocate for another 100 pending drills. + */ + dxf_pending_drills = (DxfPendingDrills *) realloc(dxf_pending_drills, dxf_max_pending_drills * sizeof(DxfPendingDrills)); + } + dxf_pending_drills[dxf_n_pending_drills].x = cx; + dxf_pending_drills[dxf_n_pending_drills].y = cy; + dxf_pending_drills[dxf_n_pending_drills].diam = radius * 2; + dxf_n_pending_drills++; + return; + } + else if (gc->drill) + return; + if (dxf_metric) { /* use metric mm */ + dxf_x0 = PCB_COORD_TO_MM(DXF_X(PCB, cx)); + dxf_y0 = PCB_COORD_TO_MM(DXF_Y(PCB, cy)); + dxf_radius = PCB_COORD_TO_MM(DXF_X(PCB, radius)); + } + else { /* use imperial mil */ + + dxf_x0 = PCB_COORD_TO_MIL(DXF_X(PCB, cx)); + dxf_y0 = PCB_COORD_TO_MIL(DXF_Y(PCB, cy)); + dxf_radius = PCB_COORD_TO_MIL(DXF_X(PCB, radius)); + } + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + dxf_write_circle(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, *//* curved or flexable pcb's ?? */ + 0.0, /* dxf_extr_x0, */ + 0.0, /* dxf_extr_y0, */ + 1.0, /* dxf_extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + dxf_radius, dxf_color, 0 /* modelspace */ + ); + dxf_id_code++; + dxf_lastX = dxf_x0; + dxf_lastY = dxf_y0; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_fill_circle () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw a filled polygon. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + * A polygon is drawn with a solid fill pattern. + * + * The filled polygon is by drawn by a (closed) polyline sequence with + * (n_coords + 1) vertices and add a SOLID hatch pattern to this polyline.\n + * This solution would allow for thieving if it were ever implemented in pcb + * (select a hatch pattern, create a boundary path, apply a scale and all the + * other stuff that is needed). + */ +static void dxf_fill_polygon(pcb_hid_gc_t gc, + /*!< graphic context. */ + int n_coords, + /*!< number of XY-coordinates. */ + int *x, + /*!< pointer to array of X-values of coordinates. */ + int *y + /*!< pointer to array of Y-values of coordinates. */ + ) { + pcb_bool m; + int i; + double dxf_x0; + double dxf_y0; + int dxf_color; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_fill_polygon () function.\n", __FILE__, __LINE__); +#endif + dxf_x0 = 0.0; + dxf_y0 = 0.0; + dxf_color = DXF_COLOR_BYLAYER; + + m = pcb_false; + if (is_mask && current_mask == HID_MASK_BEFORE) { + return; + } + dxf_use_gc(gc, 10 * 100); + /* + * return if no valid file pointer exists. + */ + if (!fp) { + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + /* + * write hatch sequence. + */ + dxf_write_hatch(fp, DXF_DEFAULT_HATCH_PATTERN_NAME, /* pattern_name, */ + dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, dxf_y0, 0.0, /* z0, *//* stacked, curved or flexable pcb's ?? */ + 0.0, /* extr_x0, */ + 0.0, /* extr_y0, */ + 1.0, /* extr_z0, */ + 0.0, /* thickness, *//* copper weight ?? */ + 1.0, /* pattern_scale, */ + 0.0, /* pixel_size, */ + 45.0, /* pattern_angle, */ + dxf_color, 0, /* modelspace, */ + 1, /* solid_fill, */ + 1, /* associative, */ + 0, /* style, */ + 1, /* pattern_style, */ + 0, /* pattern_double, */ + 0, /* pattern_def_lines, */ + 1, /* boundary_paths, */ + 0, /* seed_points, */ + 0, /* seed_x0, */ + 0 /* seed_y0, */ + ); + /* + * draw hatch boundary path polyline. + */ + dxf_write_hatch_boundary_path_polyline(fp, 2, /* path_type_flag, *//* 2 = polyline */ + 0, /* polyline_has_bulge, *//* 0 = polygons have sharp angles */ + 1, /* polyline_is_closed, *//* 1 = closed */ + n_coords + 1 /* polyline_vertices, *//* number of polyline vertices to follow */ + ); + /* + * draw hatch boundary polyline vertices, write (n_coords) + * XY-coordinates. + */ + for (i = 0; i < n_coords; i++) { + dxf_x0 = DXF_X(PCB, x[i]); + dxf_y0 = DXF_Y(PCB, y[i]); + dxf_write_hatch_boundary_path_polyline_vertex(fp, dxf_x0, dxf_y0, 0.0 /* dxf_z0 */ + ); + /* + * close polyline with first coordinate X-Y pair. + */ + dxf_x0 = DXF_X(PCB, x[0]); + dxf_y0 = DXF_Y(PCB, y[0]); + dxf_write_hatch_boundary_path_polyline_vertex(fp, dxf_x0, dxf_y0, 0.0 /* dxf_z0 */ + ); + } + dxf_id_code++; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_fill_polygon () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief Draw a filled rectangle. + * + * The usual drawing functions.\n + * "draw" means to use segments of the given width, whereas "fill" means to + * fill to a zero-width outline.\n + */ +static void dxf_fill_rect(pcb_hid_gc_t gc, + /*!< graphic context. */ + int x1, + /*!< X-value bottom left ?? point. */ + int y1, + /*!< Y-value bottom left ?? point. */ + int x2, + /*!< X-value top right ?? point. */ + int y2 + /*!< Y-value top right ?? point. */ + ) { + int dxf_color; + double dxf_x0; + double dxf_y0; + double dxf_x1; + double dxf_y1; + double dxf_x2; + double dxf_y2; + double dxf_x3; + double dxf_y3; + +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Entering dxf_fill_rect () function.\n", __FILE__, __LINE__); +#endif + /* + * return if no valid file pointer exists. + */ + if (!fp) { + fprintf(stderr, "Warning: no valid file pointer exists.\n"); + return; + } + if ((x1 == x2) && (y1 == y2)) { + fprintf(stderr, "Warning: start point and end point are identical for the entity with id-code: %x\n", dxf_id_code); + fprintf(stderr, " entity is discarded from output.\n"); + return; + } + if (dxf_color_is_byblock) { + dxf_color = DXF_COLOR_BYBLOCK; + } + else + dxf_color = gc->color; + dxf_x0 = DXF_X(PCB, x1); + dxf_y0 = DXF_Y(PCB, y1); + dxf_x1 = DXF_X(PCB, x2); + dxf_y1 = DXF_Y(PCB, y1); + dxf_x2 = DXF_X(PCB, x1); + dxf_y2 = DXF_Y(PCB, y2); + dxf_x3 = DXF_X(PCB, x2); + dxf_y3 = DXF_Y(PCB, y2); + dxf_write_solid(fp, dxf_id_code, DXF_DEFAULT_LINETYPE, /* linetype, */ + DXF_DEFAULT_LAYER, /* layer, */ + dxf_x0, /* base point, bottom left */ + dxf_y0, 0.0, /* z0, */ + dxf_x1, /* alignment point, bottom right */ + dxf_y1, 0.0, /* z1, */ + dxf_x2, /* alignment point, top left */ + dxf_y2, 0.0, /* z2, */ + dxf_x3, /* alignment point, top right */ + dxf_y3, 0.0, /* z3, */ + 0.0, /* thickness, */ + dxf_color, 0 /* modelspace */ + ); + dxf_id_code++; +#if DEBUG + fprintf(stderr, "[File: %s: line: %d] Leaving dxf_fill_rect () function.\n", __FILE__, __LINE__); +#endif +} + + +/*! + * \brief 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.\n + * For the printer, if xval and yval are zero, a calibration page is printed + * with instructions for calibrating your printer.\n + * After calibrating, nonzero xval and yval are passed according to the + * instructions.\n + * Metric is nonzero if the user prefers metric units, else inches are used.\n + * Calibrate a DXF file ?.\n + * Since we do not calibrate a DXF file, we ignore this one. + */ +static void dxf_calibrate(double xval, + /*!< X-value. */ + double yval + /*!< Y-value. */ + ) { + /* Intentionally: do nothing here */ +} + + +/*! + * \brief Sets the crosshair. + * + * Which may differ from the pointer depending on grid and pad snap.\n + * Note that the HID is responsible for hiding, showing, redrawing, etc.\n + * The core just tells it what coordinates it's actually using.\n + * Note that this routine may need to know what "pcb units" are so it can + * display them in mm or mils accordingly.\n + * Set a crosshair in a DXF file ?.\n + * Since it is useless to set a crosshair in a DXF file, we ignore this one. + */ +static void dxf_set_crosshair(int x, + /*!< X-value of coordinate. */ + int y + /*!< Y-value of coordinate. */ + ) { + /* Intentionally: do nothing here */ +} + + +/*! + * \brief Show item ?. + */ +static void dxf_show_item(void *item) +{ +} + + +/*! + * \brief Send beep signal to stdout ?. + */ +static void dxf_beep(void) +{ + putchar(7); + fflush(stdout); +} + + +/*! + * \brief Show progress ?. + */ +static void dxf_progress(int dxf_so_far, int dxf_total, const char *dxf_message) +{ +} + +const char *dxf_cookie = "dxf exporter"; + +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); +} + +/*! + * \brief Call this as soon as possible from main(). + * + * Initialise and register the DXF HID. + * No other HID calls are valid until this is called. + */ +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 = "DXF export"; + dxf_hid.exporter = 1; + dxf_hid.poly_before = 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.calibrate = dxf_calibrate; + dxf_hid.set_crosshair = dxf_set_crosshair; + dxf_hid.show_item = dxf_show_item; + dxf_hid.beep = dxf_beep; + dxf_hid.progress = dxf_progress; + + dxf_hid.make_gc = dxf_make_gc; + dxf_hid.destroy_gc = dxf_destroy_gc; + dxf_hid.use_mask = dxf_use_mask; + 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_rect = dxf_fill_rect; + + pcb_hid_register_hid(&dxf_hid); + + pcb_hid_register_attributes(dxf_options, sizeof(dxf_options) / sizeof(dxf_options[0]), dxf_cookie, 0); + + return 0; +} + + +/* EOF */ Index: tags/1.2.3/src_plugins/export_dxf/export_dxf.pup =================================================================== --- tags/1.2.3/src_plugins/export_dxf/export_dxf.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_dxf/export_dxf.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short DXF pcb_exporter +$long Export dxf +$state WIP +default disable-all +autoload 1 Index: tags/1.2.3/src_plugins/export_fidocadj/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_fidocadj/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_fidocadj/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_fidocadj + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_fidocadj/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_fidocadj/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_fidocadj/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_fidocadj/export_fidocadj.pup =================================================================== --- tags/1.2.3/src_plugins/export_fidocadj/export_fidocadj.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_fidocadj/export_fidocadj.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short FidoCadJ .fcd pcb_exporter +$long Export to FidoCadJ format (.fcd) +$state WIP +default disable-all +autoload 1 Index: tags/1.2.3/src_plugins/export_fidocadj/fidocadj.c =================================================================== --- tags/1.2.3/src_plugins/export_fidocadj/fidocadj.c (nonexistent) +++ tags/1.2.3/src_plugins/export_fidocadj/fidocadj.c (revision 8969) @@ -0,0 +1,363 @@ + /* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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 = 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 = 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 foo.pcb [fidocadj options]\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.3/src_plugins/export_gcode/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_gcode/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gcode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_gcode/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_gcode/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_gcode/auxiliary.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/auxiliary.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/auxiliary.h (revision 8969) @@ -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 */ +static inline PCB_FUNC_UNUSED 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] */ +static inline PCB_FUNC_UNUSED 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; +} + +/* ---------------------------------------------------------------------- */ +/* some useful macros. Note: the "mod" macro 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" macro 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 */ + +static inline PCB_FUNC_UNUSED int mod(int a, int n) +{ + return a >= n ? a % n : a >= 0 ? a : n - 1 - (-1 - a) % n; +} + +static inline PCB_FUNC_UNUSED 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.3/src_plugins/export_gcode/bitmap.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/bitmap.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/bitmap.h (revision 8969) @@ -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. */ +static inline PCB_FUNC_UNUSED void bm_free(potrace_bitmap_t * bm) +{ + if (bm) { + free(bm->map); + } + free(bm); +} + +/* return new un-initialized bitmap. NULL with errno on error */ +static inline PCB_FUNC_UNUSED 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. */ +static inline PCB_FUNC_UNUSED 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. */ +static inline PCB_FUNC_UNUSED 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. */ +static inline PCB_FUNC_UNUSED 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.3/src_plugins/export_gcode/curve.c =================================================================== --- tags/1.2.3/src_plugins/export_gcode/curve.c (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/curve.c (revision 8969) @@ -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.3/src_plugins/export_gcode/curve.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/curve.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/curve.h (revision 8969) @@ -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.3/src_plugins/export_gcode/decompose.c =================================================================== --- tags/1.2.3/src_plugins/export_gcode/decompose.c (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/decompose.c (revision 8969) @@ -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.3/src_plugins/export_gcode/decompose.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/decompose.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/decompose.h (revision 8969) @@ -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.3/src_plugins/export_gcode/export_gcode.pup =================================================================== --- tags/1.2.3/src_plugins/export_gcode/export_gcode.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/export_gcode.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short gcode pcb_exporter +$long Export to gcode +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_gcode/gcode.c =================================================================== --- tags/1.2.3/src_plugins/export_gcode/gcode.c (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/gcode.c (revision 8969) @@ -0,0 +1,927 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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 = 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 = 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 = 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_use_mask(pcb_mask_op_t use_it) +{ + /* does nothing */ +} + +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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + 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]); + points[i].y = pcb_to_gcode(y[i]); + } + gdImageSetThickness(gcode_im, 0); + linewidth = 0; + gdImageFilledPolygon(gcode_im, points, n_coords, gc->color->c); + free(points); +/* printf("FillPoly\n"); */ +} + +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 foo.pcb [gcode options]\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.poly_before = 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.use_mask = gcode_use_mask; + 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_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.3/src_plugins/export_gcode/gcode.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/gcode.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/gcode.h (revision 8969) @@ -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.3/src_plugins/export_gcode/lists.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/lists.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/lists.h (revision 8969) @@ -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.3/src_plugins/export_gcode/potracelib.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/potracelib.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/potracelib.h (revision 8969) @@ -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.3/src_plugins/export_gcode/trace.c =================================================================== --- tags/1.2.3/src_plugins/export_gcode/trace.c (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/trace.c (revision 8969) @@ -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.3/src_plugins/export_gcode/trace.h =================================================================== --- tags/1.2.3/src_plugins/export_gcode/trace.h (nonexistent) +++ tags/1.2.3/src_plugins/export_gcode/trace.h (revision 8969) @@ -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.3/src_plugins/export_gerber/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_gerber/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_gerber/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_gerber + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_gerber/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_gerber/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_gerber/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_gerber/export_gerber.pup =================================================================== --- tags/1.2.3/src_plugins/export_gerber/export_gerber.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_gerber/export_gerber.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short Gerber pcb_exporter +$long Export to gerber +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_gerber/gerber.c =================================================================== --- tags/1.2.3/src_plugins/export_gerber/gerber.c (nonexistent) +++ tags/1.2.3/src_plugins/export_gerber/gerber.c (revision 8969) @@ -0,0 +1,1273 @@ +#include "config.h" + +#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 "draw.h" +#include "layer.h" +#include "pcb-printf.h" +#include "plugins.h" +#include "hid_helper.h" +#include "compat_misc.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() + +/*----------------------------------------------------------------------------*/ +/* Function prototypes */ +/*----------------------------------------------------------------------------*/ + +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_use_mask(pcb_mask_op_t use_it); +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(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 int current_mask; +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 mask_issued; +static int gerber_debug; + +enum ApertureShape { + ROUND, /* Shaped like a circle */ + OCTAGON, /* octagonal shape */ + SQUARE, /* Shaped like a square */ + ROUNDCLEAR, /* clearance in negatives */ + SQUARECLEAR, + THERMAL /* negative thermal relief */ +}; +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; +#if 0 + case THERMAL: + fprintf(f, "%%AMTHERM%d*7,0,0,%.4f,%.4f,%.4f,45*%%\r\n" + "%%ADD%dTHERM%d*%%\r\n", dCode, gap / 100000.0, width / 100000.0, finger / 100000.0, dCode, dCode); + break; + case ROUNDCLEAR: + fprintf(f, "%%ADD%dC,%.4fX%.4f*%%\r\n", dCode, gap / 100000.0, width / 100000.0); + break; + case SQUARECLEAR: + fprintf(f, "%%ADD%dR,%.4fX%.4fX%.4fX%.4f*%%\r\n", + dCode, gap / 100000.0, gap / 100000.0, width / 100000.0, width / 100000.0); + break; +#else + default: + break; +#endif + } +} + +/* 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", + 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); +} + + +#undef fmatch + + +static void assign_file_suffix(char *dest, 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; + } + + 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); + + 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 + 40); + 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); /* 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(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); + current_mask = 0; + if (group < 0 || group != lastgroup) { + time_t currenttime; + 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, layer, flags); + f = 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. */ + currenttime = time(NULL); + { + /* avoid gcc complaints */ + const char *fmt = "%c UTC"; + strftime(utcTime, sizeof utcTime, fmt, gmtime(¤ttime)); + } + /* 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_get_user_name()); + + 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_use_mask(pcb_mask_op_t use_it) +{ + current_mask = use_it; + if ((f != NULL) && (gerber_debug)) + fprintf(f, "G04 hid debug mask: %d*\r\n", use_it); + if ((use_it == HID_MASK_OFF) || (use_it == HID_MASK_INIT)) + mask_issued = -1; +} + +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) && (current_mask != mask_issued)) { + if (current_mask == HID_MASK_SET) { + fprintf(f, "%%LPD*%%\r\n"); + mask_issued = current_mask; + } + else if (current_mask == HID_MASK_CLEAR) { + fprintf(f, "%%LPC*%%\r\n"); + mask_issued = current_mask; + } + } + + 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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + pcb_bool m = pcb_false; + int i; + int firstTime = 1; + pcb_coord_t startX = 0, startY = 0; + + if (is_mask && current_mask == HID_MASK_BEFORE) + return; + + use_gc(gc, 10 * 100); + if (!f) + return; + fprintf(f, "G36*\r\n"); + for (i = 0; i < n_coords; i++) { + if (x[i] != lastX) { + m = pcb_true; + lastX = x[i]; + pcb_fprintf(f, "X%.0mc", gerberX(PCB, lastX)); + } + if (y[i] != lastY) { + m = pcb_true; + lastY = y[i]; + pcb_fprintf(f, "Y%.0mc", gerberY(PCB, lastY)); + } + if (firstTime) { + firstTime = 0; + startX = x[i]; + startY = y[i]; + 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_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 foo.pcb [gerber options]\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) +{ +} + +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.use_mask = gerber_use_mask; + 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_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.3/src_plugins/export_ipcd356/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_ipcd356/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_ipcd356/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ipcd356 + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_ipcd356/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_ipcd356/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_ipcd356/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_ipcd356/export_ipcd356.pup =================================================================== --- tags/1.2.3/src_plugins/export_ipcd356/export_ipcd356.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_ipcd356/export_ipcd356.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short IPC-D-356 Netlist pcb_exporter +$long IPC-D-356 Netlist export. +$state Work-in-progress +default disable-all +autoload 1 Index: tags/1.2.3/src_plugins/export_ipcd356/ipcd356.c =================================================================== --- tags/1.2.3/src_plugins/export_ipcd356/ipcd356.c (nonexistent) +++ tags/1.2.3/src_plugins/export_ipcd356/ipcd356.c (revision 8969) @@ -0,0 +1,632 @@ +/*! + * + * \brief IPC-D-356 Netlist export. + * + * \author Copyright (C) 2012 Jerome Marchand (Jerome.Marchand@gmail.com) + * + *
    + * + *

    Copyright.

    \n + * + * 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 "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) +{ + time_t currenttime; + char utcTime[64]; + const char *fmt = "%c UTC"; + + currenttime = time(NULL); + strftime(utcTime, sizeof utcTime, fmt, gmtime(¤ttime)); + + fprintf(fd, "C IPC-D-356 Netlist generated by gEDA 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 = 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.3/src_plugins/export_lpr/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_lpr/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_lpr/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_lpr + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_lpr/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_lpr/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_lpr/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_lpr/export_lpr.pup =================================================================== --- tags/1.2.3/src_plugins/export_lpr/export_lpr.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_lpr/export_lpr.pup (revision 8969) @@ -0,0 +1,7 @@ +$class export +$short lpr pcb_exporter (printer) +$long Export to lpr (using export_ps to generate postscript) +$state works +default buildin +dep export_ps +autoload 1 Index: tags/1.2.3/src_plugins/export_lpr/lpr.c =================================================================== --- tags/1.2.3/src_plugins/export_lpr/lpr.c (nonexistent) +++ tags/1.2.3/src_plugins/export_lpr/lpr.c (revision 8969) @@ -0,0 +1,155 @@ +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "data.h" +#include "plugins.h" +#include "compat_misc.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 = popen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + ps_hid_export_to_file(f, options); + + fclose(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 foo.pcb [lpr options]\n\n"); + return 0; +} + +static void plugin_lpr_uninit(void) +{ + pcb_hid_remove_actions_by_cookie(lpr_cookie); +} + +int pplg_check_ver_export_lpr(int ver_needed) { return 0; } + +void pplg_uninit_export_lpr(void) +{ +} + +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.poly_before = 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.3/src_plugins/export_nelma/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_nelma/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_nelma/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_nelma + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_nelma/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_nelma/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_nelma/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_nelma/export_nelma.pup =================================================================== --- tags/1.2.3/src_plugins/export_nelma/export_nelma.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_nelma/export_nelma.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short nelma pcb_exporter +$long Export to nelma (Numerical capacitance calculator) +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_nelma/nelma.c =================================================================== --- tags/1.2.3/src_plugins/export_nelma/nelma.c (nonexistent) +++ tags/1.2.3/src_plugins/export_nelma/nelma.c (revision 8969) @@ -0,0 +1,1010 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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 = 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 = 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_use_mask(pcb_mask_op_t use_it) +{ + /* does nothing */ +} + +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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + 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]); + points[i].y = pcb_to_nelma(y[i]); + } + gdImageSetThickness(nelma_im, 0); + linewidth = 0; + gdImageFilledPolygon(nelma_im, points, n_coords, gc->color->c); + free(points); +} + +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 foo.pcb [nelma options]\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) +{ +} + +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.poly_before = 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.use_mask = nelma_use_mask; + 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_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.3/src_plugins/export_openscad/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_openscad/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_openscad + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_openscad/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_openscad/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/Plug.tmpasm (revision 8969) @@ -0,0 +1,12 @@ +put /local/pcb/mod {export_openscad} +put /local/pcb/mod/OBJS [@ + $(PLUGDIR)/export_openscad/scad.o + $(PLUGDIR)/export_openscad/scadproto.o + $(PLUGDIR)/export_openscad/scadcomp.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.3/src_plugins/export_openscad/export_openscad.pup =================================================================== --- tags/1.2.3/src_plugins/export_openscad/export_openscad.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/export_openscad.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short openscad pcb_exporter +$long Export openscad +$state WIP +default disable-all +autoload 1 Index: tags/1.2.3/src_plugins/export_openscad/scad.c =================================================================== --- tags/1.2.3/src_plugins/export_openscad/scad.c (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/scad.c (revision 8969) @@ -0,0 +1,1175 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * OpenSCAD export HID + * This code is based on the GERBER and VRML 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "board.h" +#include "math_helper.h" +#include "data.h" +#include "error.h" +#include "buffer.h" +#include "conf_core.h" +#include "layer.h" +#include "plugins.h" + +#include "hid.h" +#include "hid_draw_helpers.h" +#include "hid_nogui.h" +#include "hid_init.h" +#include "hid_attrib.h" +#include "hid_helper.h" + +#include "scad.h" + +/**************************************************************************************************** +* VRML export filter parameters and options +****************************************************************************************************/ + +static const char *export_modes[] = { + "None", + "Boxes", + "Simple", + "Realistic", + 0 +}; + +static const char *board_outlines[] = { + "None", + "Outline", + "Board", + 0 +}; + +static const char *copper_colors[] = { + "Copper", + "Gold", + "HAL", + 0 +}; + +static const char *mask_colors[] = { + "None", + "Green", + "Blue", + "Red", + 0 +}; + +static const char *board_cuts[] = { + "All", + "Top", + "Top_only", + "Bottom", + "Bottom_only" +}; + +static char *mask_color_table[] = { + "", SCAD_MASK_COLOR_G, SCAD_MASK_COLOR_B, SCAD_MASK_COLOR_R +}; + +static char *finish_color_table[] = { + SCAD_COPPER_COLOR, SCAD_COPPER_COLOR_GOLD, SCAD_COPPER_COLOR_TIN +}; + + + + +static pcb_hid_t scad_hid; + +static int drill_layer, outline_layer, mask_layer; +static int layer_open, fresh_layer; +static char layer_id[64]; + +static struct { + int draw; + int exp; + float z_offset; + int solder; + int component; +} group_data[PCB_MAX_LAYERGRP]; + + +#define HA_scadfile 0 +#define HA_outline_type 1 +#define HA_exp_component 2 +#define HA_exp_copper 3 +#define HA_exp_silk 4 +#define HA_exp_inner_layers 5 +#define HA_mask_color 6 +#define HA_copper_color 7 +#define HA_minimal_drill 9 +#define HA_board_cut 10 + +static pcb_hid_attribute_t scad_options[] = { +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --scad-file +Name of the OpenSCAD model file. +@end ftable +%end-doc +*/ + { + "scad_file", "SCAD file name", PCB_HATT_STRING, 0, 0, + { + 0, 0, 0, 0}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --board_outline +How the board outline is created. @samp{None} - no board outline (inner layers copper is visible), @samp{Outline} - board outline is constructed from @samp{outline} layer, +@samp{Board} - board outline ha rectangular shape, dimensions are taken from board properties. Default: @samp{Board}. +@end ftable +%end-doc +*/ + { + "board_outline", "Board outline", + PCB_HATT_ENUM, + 0, 0, + { + 2, 0, 0, 0}, board_outlines, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --components +Populates board with components. Values: @samp{None}, @samp{Boxes}, @samp{Simple}, @samp{Realistic}. Default: @samp{Realistic}. +@end ftable +%end-doc +*/ + { + "components", "Export components", + PCB_HATT_ENUM, + 0, 0, + { + 3, 0, 0, 0}, export_modes, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --copper +Exports copper tracks, pads, pins and vias. Default: @samp{false}. +@end ftable +%end-doc +*/ + { + "copper", "Export tracks and copper planes", PCB_HATT_BOOL, 0, 0, + { + 0, 0, 0, 0}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --silk_layers +Exports silk screen layers. Default: @samp{false}. +@end ftable +%end-doc +*/ + { + "silk_layers", "Export silk layers", PCB_HATT_BOOL, 0, 0, + { + 0, 0, 0, 0}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --inner_layers +Exports inner layers (normally invisible, hidden inside board). Default: @samp{false}. +@end ftable +%end-doc +*/ + { + "innner_layers", "Export inner layers", PCB_HATT_BOOL, 0, 0, + { + 0, 0, 0, 0}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --solder_mask +Type of solder mask. Available options: @samp{None}, @samp{Green}, @samp{Red} and @samp{Blue}. Default: @samp{None}. +@end ftable +%end-doc +*/ + { + "solder_mask", "Solder mask color", PCB_HATT_ENUM, 0, 0, + { + 0, 0, 0, 0}, mask_colors, 0}, + { +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --copper_finish +Type of copper finish. Values: @samp{Copper}, @samp{Gold} and @samp{HAL}. Default: @samp{Copper}. +@end ftable +%end-doc +*/ + "copper_finish", "Surface finish of copper", + PCB_HATT_ENUM, + 0, 0, + { + 0, 0, 0, 0}, copper_colors, 0}, + + { + " ", " ", PCB_HATT_LABEL, 0, 0, + { + 0, 0, 0, 0}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --min_drill +Minimal drill to be exported. Default: @samp{1mm}. +@end ftable +%end-doc +*/ + { + "min_drill", "Minimal drill to export", PCB_HATT_COORD, PCB_MM_TO_COORD(0), + PCB_MM_TO_COORD(10), + { + 0, 0, 0, PCB_MM_TO_COORD(1)}, 0, 0}, +/* +%start-doc options "Advanced OpenSCAD Export" +@ftable @code +@item --board cut +Type of board cut. Values: @samp{All}, @samp{Top}, @samp{Top only}, @samp{Bottom}, @samp{Bottom only}. Default: @samp{None}. +@end ftable +%end-doc +*/ + { + "board_cut", "Section of board to be exported (3D print support)", + PCB_HATT_ENUM, + 0, 0, + { + 0, 0, 0, 0}, board_cuts, 0}, +}; + +#define NUM_OPTIONS (sizeof(scad_options)/sizeof(scad_options[0])) + +static pcb_hid_attr_val_t scad_values[NUM_OPTIONS]; + +/****************************************************************************************************/ + +FILE *scad_output; + +static const char *scad_filename = 0; + +static int opt_exp_silk; +static int opt_exp_component; +static int opt_exp_inner_layers; +static int opt_exp_copper; +static int opt_outline_type; +static int opt_copper_color; +static int opt_mask_color; +static pcb_coord_t opt_minimal_drill; +static int opt_board_cut; + +static int lastseq = 0; +static pcb_mask_op_t current_mask; + +static float scaled_layer_thickness; + +static int n_alloc_outline_segments, n_outline_segments; +static t_outline_segment *outline_segments; + +static void scad_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y); +static void scad_emit_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y, float thickness); + + +/* scaling function - all output is in milimeters */ + +float scad_scale_coord(float x) +{ + return x * METRIC_SCALE; +} + + + +static void scad_close_layer() +{ + + if (!outline_layer) { + if (drill_layer) { + fprintf(scad_output, "];\n\n"); + } + else { + fprintf(scad_output, "}\n}\n\n"); + } + + fprintf(scad_output, "\n// END_OF_LAYER %s\n\n", layer_id); + } + layer_open = 0; +} + + +/******************************************* +* Export filter implementation starts here +********************************************/ + +static pcb_hid_attribute_t *scad_get_export_options(int *n) +{ + static char *last_made_filename = 0; + if (PCB) + pcb_derive_default_filename(PCB->Filename, &scad_options[HA_scadfile], ".scad", &last_made_filename); + +/* scad_options[HA_minimal_drill].coord_value = scad_options[HA_minimal_drill].*/ + if (n) + *n = NUM_OPTIONS; + return scad_options; +} + +/******************************************* +* main export function +* - collect information about used layers and their grouping +* - calculates positions olaers, dependiing on options and number of layer groups +* - calls the export, exports the board layout +* - generates the board outline, based on (depends on user selection): +* - physical dimensions set in preferences +* - lines drawn on "Outline" layer +* - polygons drawn on "Shape" layer +* - populates the board with components +********************************************/ + +static void init_outline() +{ + outline_segments = 0; + n_alloc_outline_segments = 0; + n_outline_segments = 0; +} + +static void add_outline_segment(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + if (!n_alloc_outline_segments) { + outline_segments = (t_outline_segment *) malloc(sizeof(t_outline_segment) * 50); + n_alloc_outline_segments = 50; + if (!outline_segments) { + pcb_message(PCB_MSG_ERROR, "openscad: cannot allocate memory for board outline. Board outline cannot be created.\n"); + return; + } + } + else { + if (n_alloc_outline_segments == n_outline_segments) { + t_outline_segment *os = (t_outline_segment *) realloc(outline_segments, + sizeof(t_outline_segment) * (n_alloc_outline_segments + 50)); + + if (os) { + outline_segments = os; + n_alloc_outline_segments = n_alloc_outline_segments + 50; + } + else { + pcb_message(PCB_MSG_ERROR, "openscad: cannot allocate more memory for board outline. Board outline will be incomplete.\n"); + return; + } + } + } + + outline_segments[n_outline_segments].processed = 0; + outline_segments[n_outline_segments].x1 = x1; + outline_segments[n_outline_segments].y1 = y1; + outline_segments[n_outline_segments].x2 = x2; + outline_segments[n_outline_segments].y2 = y2; + n_outline_segments++; +} + + +typedef struct { + pcb_coord_t x; + pcb_coord_t y; + int marker; +} t_OutlinePoint; + +static int is_same_point(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + return (abs(x1 - x2) < SCAD_MIN_OUTLINE_DIST) + && (abs(y1 - y2) < SCAD_MIN_OUTLINE_DIST); +} + + +void scad_process_outline() +{ + int i, j, n; + t_OutlinePoint *op; + + if (outline_segments && n_outline_segments) { + + op = malloc(n_outline_segments * 2 * sizeof(t_OutlinePoint)); + + if (op != NULL) { + + n = 0; + for (i = 0; i < n_outline_segments; i++) { + + if (!outline_segments[i].processed) { + outline_segments[i].processed = 1; + op[n].x = outline_segments[i].x1; + op[n].y = outline_segments[i].y1; + op[n].marker = 1; + op[n + 1].x = outline_segments[i].x2; + op[n + 1].y = outline_segments[i].y2; + op[n + 1].marker = 0; + n += 2;; + do { + for (j = i + 1; j < n_outline_segments; j++) { + if (!outline_segments[j].processed) { + if (is_same_point(op[n - 1].x, op[n - 1].y, outline_segments[j].x1, outline_segments[j].y1)) { + op[n - 1].x = (op[n - 1].x + outline_segments[j].x1) / 2; + op[n - 1].y = (op[n - 1].y + outline_segments[j].y1) / 2; + op[n].x = outline_segments[j].x2; + op[n].y = outline_segments[j].y2; + n++; + outline_segments[j].processed = 1; + break; + } + else if (is_same_point(op[n - 1].x, op[n - 1].y, outline_segments[j].x2, outline_segments[j].y2)) { + op[n - 1].x = (op[n - 1].x + outline_segments[j].x2) / 2; + op[n - 1].y = (op[n - 1].y + outline_segments[j].y2) / 2; + op[n].x = outline_segments[j].x1; + op[n].y = outline_segments[j].y1; + n++; + outline_segments[j].processed = 1; + break; + } + } + } + } + while (j < n_outline_segments); + } + } + + fprintf(scad_output, "module board_outline () {\n\tpolygon(["); + + /* Outline points */ + for (i = 0; i < n; i++) { + fprintf(scad_output, "\t\t[%f, %f]%s\n", + scad_scale_coord((float) op[i].x), -scad_scale_coord((float) op[i].y), (i < (n - 1)) ? ", " : ""); + } + + /* Outline paths */ + fprintf(scad_output, "\t],[\n\t\t"); + + fprintf(scad_output, "\t\t["); + for (i = 0; i < n; i++) { +/* if (!(i % 10) && i) + fprintf (scad_output, "\n\t\t");*/ + if (i > 0 && op[i].marker) + fprintf(scad_output, "],\n\t\t["); +/* fprintf (scad_output, "%d%s", i, (i < (n - 1)) ? ", " : "");*/ + fprintf(scad_output, "%d%s", i, ((i < (n - 1)) && op[i + 1].marker == 0) ? ", " : ""); + } + fprintf(scad_output, "\t]]);\n"); + fprintf(scad_output, "}\n\n"); + } + else { + pcb_message(PCB_MSG_ERROR, "openscad: cannot allocate more memory for board outline. Board outline will be incomplete.\n"); + } + if (op) + free(op); + free(outline_segments); + } +} + +static void scad_do_export(pcb_hid_attr_val_t * options) +{ + int i; + int inner_layers; + float layer_spacing, layer_offset, cut_offset = 0.; + pcb_hid_expose_ctx_t ctx; + pcb_layer_t *layer; + pcb_layergrp_id_t gbottom, gtop; + + conf_force_set_bool(conf_core.editor.thin_draw, 0); + conf_force_set_bool(conf_core.editor.thin_draw_poly, 0); + + if (!options) { + scad_get_export_options(0); + for (i = 0; i < NUM_OPTIONS; i++) + scad_values[i] = scad_options[i].default_val; + options = scad_values; + } + opt_mask_color = options[HA_mask_color].int_value; + opt_exp_silk = options[HA_exp_silk].int_value; + opt_exp_component = options[HA_exp_component].int_value; + opt_exp_inner_layers = options[HA_exp_inner_layers].int_value; + opt_exp_copper = options[HA_exp_copper].int_value; + opt_outline_type = options[HA_outline_type].int_value; + opt_copper_color = options[HA_copper_color].int_value; + opt_minimal_drill = options[HA_minimal_drill].coord_value; + opt_board_cut = options[HA_board_cut].int_value; + + scad_filename = options[HA_scadfile].str_value; + if (!scad_filename) + scad_filename = "unknown.scad"; + + scad_output = fopen(scad_filename, "w"); + if (scad_output == NULL) { + pcb_message(PCB_MSG_ERROR, "openscad: could not open %s for writing.\n", scad_filename); + goto quit; + } + + scad_write_prologue(PCB->Filename); + + memset(group_data, 0, sizeof(group_data)); + + if (pcb_layergrp_list(PCB, PCB_LYT_SILK | PCB_LYT_BOTTOM, &gbottom, 1) > 0) + group_data[gbottom].solder = 1; + + if (pcb_layergrp_list(PCB, PCB_LYT_SILK | PCB_LYT_TOP, >op, 1) > 0) + group_data[gtop].component = 1; + + for (i = 0; i < pcb_max_layer; i++) { + if (pcb_layer_flags(PCB, i) & PCB_LYT_SILK) + continue; + layer = PCB->Data->Layer + i; + if (!pcb_layer_is_empty_(PCB, layer)) + group_data[pcb_layer_get_group(PCB, i)].draw = 1; + } + + inner_layers = 0; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (group_data[i].draw && !(group_data[i].component || group_data[i].solder)) { + inner_layers++; + } + } + + layer_spacing = BOARD_THICKNESS / ((float) inner_layers + 1); + layer_offset = BOARD_THICKNESS / 2. - layer_spacing; + for (i = 0; i < pcb_max_group(PCB); i++) { + if (group_data[i].component) { + group_data[i].z_offset = (BOARD_THICKNESS / 2.) + (OUTER_COPPER_THICKNESS / 2.); + } + else if (group_data[i].solder) { + group_data[i].z_offset = -(BOARD_THICKNESS / 2.) - (OUTER_COPPER_THICKNESS / 2.); + } + else if (group_data[i].draw) { + group_data[i].z_offset = layer_offset; + layer_offset -= layer_spacing; + } + } + + ctx.view.X1 = 0; + ctx.view.Y1 = 0; + ctx.view.X2 = PCB->MaxWidth; + ctx.view.Y2 = PCB->MaxHeight; + + layer_open = 0; + + pcb_hid_expose_all(&scad_hid, &ctx); + +/* And now .... Board outlines */ + + if (opt_outline_type == SCAD_OUTLINE_SIZE) { + fprintf(scad_output, "module board_outline () {\n\tpolygon("); + fprintf(scad_output, "[[0,0],[0,%f],[%f,%f],[%f,0]],\n", + -scad_scale_coord((float) PCB->MaxHeight), + scad_scale_coord((float) PCB->MaxWidth), + -scad_scale_coord((float) PCB->MaxHeight), scad_scale_coord((float) PCB->MaxWidth)); + fprintf(scad_output, "[[0,1,2,3]]);\n"); + fprintf(scad_output, "}\n\n"); + + } + else if (opt_outline_type == SCAD_OUTLINE_OUTLINE /* and collected lines */ ) { + scad_process_outline(); + } + + if (layer_open) { + scad_close_layer(); + } + + scad_generate_holes(); + if (opt_exp_copper) + scad_generate_plating(); + + if (opt_outline_type != SCAD_OUTLINE_NONE) + scad_generate_board(); + + if (opt_mask_color != SCAD_MASK_NONE && opt_outline_type != SCAD_OUTLINE_NONE) + scad_generate_mask(); + + + if (EXPORT_COMPONENTS) { + fprintf(scad_output, "/***************************************************/\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/* Components */\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/***************************************************/\n"); + scad_process_components(opt_exp_component); + } + + + fprintf(scad_output, "/***************************************************/\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/* Final board assembly */\n"); + fprintf(scad_output, "/* Here is the complete board built from */\n"); + fprintf(scad_output, "/* pre-generated modules */\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/***************************************************/\n"); + + if (opt_board_cut != SCAD_CUT_COMPLETE) { + fprintf(scad_output, "intersection () {\n\tunion () {\n"); + } + + if (opt_exp_copper) { + for (i = 0; i < pcb_max_group(PCB); i++) { + if (group_data[i].exp) { +/* printf("%d\n",i); */ + + if (group_data[i].component || group_data[i].solder || opt_exp_inner_layers) { + fprintf(scad_output, "\t\tcolor (%s)\n", finish_color_table[opt_copper_color]); + fprintf(scad_output, "\t\t\tdifference() {\n"); + fprintf(scad_output, "\t\t\t\tlayer_%02d_body(%f);\n", i, group_data[i].z_offset); + fprintf(scad_output, "\t\t\t\tall_holes();\n"); + fprintf(scad_output, "\t\t\t}\n\n"); + } + + } + } + } + + if (opt_exp_silk) { + fprintf(scad_output, "\t\tcolor (%s)\n", SCAD_SILK_COLOR); + fprintf(scad_output, "\t\t\tlayer_topsilk_body(%f);\n\n", + (opt_mask_color != SCAD_MASK_NONE + && opt_outline_type != SCAD_OUTLINE_NONE) ? SILK_LAYER_OFFSET2 : SILK_LAYER_OFFSET); + fprintf(scad_output, "\t\tcolor (%s)\n", SCAD_SILK_COLOR); + fprintf(scad_output, "\t\t\tlayer_bottomsilk_body(%f);\n\n", + (opt_mask_color != SCAD_MASK_NONE + && opt_outline_type != SCAD_OUTLINE_NONE) ? -SILK_LAYER_OFFSET2 : -SILK_LAYER_OFFSET); + } + + if (opt_exp_copper) { + fprintf(scad_output, "\t\tcolor (%s)\n", finish_color_table[opt_copper_color]); + fprintf(scad_output, "\t\t\tall_plating();\n\n"); + } + + if (opt_outline_type != SCAD_OUTLINE_NONE) { + fprintf(scad_output, "\t\tcolor (%s)\n", SCAD_BOARD_COLOR); + fprintf(scad_output, "\t\t\tdifference() {\n"); + fprintf(scad_output, "\t\t\t\tboard_body();\n"); + fprintf(scad_output, "\t\t\t\tall_holes();\n"); + fprintf(scad_output, "\t\t\t}\n\n"); + } + if (opt_mask_color != SCAD_MASK_NONE && opt_outline_type != SCAD_OUTLINE_NONE) { + fprintf(scad_output, "\t\tcolor (%s) translate ([0,0,%f])\n", + mask_color_table[opt_mask_color], (BOARD_THICKNESS + MASK_THICKNESS) / 2.); + fprintf(scad_output, "\t\t\tdifference() {\n"); + fprintf(scad_output, "\t\t\t\tmask_surface();\n"); + fprintf(scad_output, "\t\t\t\tlayer_topmask_body();\n"); + fprintf(scad_output, "\t\t\t}\n\n"); + fprintf(scad_output, "\t\tcolor (%s) translate ([0,0,%f])\n", + mask_color_table[opt_mask_color], -(BOARD_THICKNESS + MASK_THICKNESS) / 2.); + fprintf(scad_output, "\t\t\tdifference() {\n"); + fprintf(scad_output, "\t\t\t\tmask_surface();\n"); + fprintf(scad_output, "\t\t\t\tlayer_bottommask_body();\n"); + fprintf(scad_output, "\t\t\t}\n\n"); + } + + if (EXPORT_COMPONENTS) + fprintf(scad_output, "\t\tall_components();\n"); + + if (opt_board_cut != SCAD_CUT_COMPLETE) { + switch (opt_board_cut) { + case SCAD_CUT_TOP: + cut_offset = 0.; + break; + case SCAD_CUT_TOP_ONLY: + cut_offset = -BOARD_THICKNESS / 2.; + break; + case SCAD_CUT_BOTTOM: + cut_offset = -100.; + break; + case SCAD_CUT_BOTTOM_ONLY: + cut_offset = -100. + BOARD_THICKNESS / 2.; + break; + } + fprintf(scad_output, "\t}\n"); + fprintf(scad_output, "\t\t translate ([%f,%f,%f]) ", -25., + -scad_scale_coord((float) PCB->MaxHeight) / 2. - 25., cut_offset); + fprintf(scad_output, "\t\t cube ([%f,%f,100]);\n", + scad_scale_coord((float) PCB->MaxWidth) + 50., scad_scale_coord((float) PCB->MaxHeight)); + fprintf(scad_output, "}\n"); + } + + fprintf(scad_output, "// END_OF_BOARD\n"); + fclose(scad_output); + quit:; + conf_update(NULL); /* restore forced sets */ +} + +static void scad_parse_arguments(int *argc, char ***argv) +{ + pcb_hid_parse_command_line(argc, argv); +} + +static int scad_set_layer_group(pcb_layergrp_id_t group, pcb_layer_id_t layer, unsigned int flags, int is_empty) +{ + int layer_ok; + + if (layer_open) { + scad_close_layer(); + } + + drill_layer = 0; + mask_layer = 0; + outline_layer = 0; + fresh_layer = 1; + + if (flags & PCB_LYT_UI) + return 0; + + if ((flags & PCB_LYT_INVIS) || (flags & PCB_LYT_ASSY)) + return 0; + + if (flags & PCB_LYT_COPPER) { + layer_ok = (opt_exp_inner_layers || group_data[group].component || group_data[group].solder) && opt_exp_copper; + } + else { + layer_ok = 1; + } + + if ((flags & PCB_LYT_OUTLINE)) { + if (opt_outline_type == SCAD_OUTLINE_OUTLINE) { + outline_layer = 1; + layer_ok = 1; + init_outline(); + n_alloc_outline_segments = 0; + n_outline_segments = 0; + } + else + return 0; + } + + if (!layer_ok) + return 0; + + if (group >= 0 && group < pcb_max_group(PCB)) { + if (flags & PCB_LYT_SILK) { + if (!opt_exp_silk) + return 0; + scaled_layer_thickness = SILK_LAYER_THICKNESS; + if (flags & PCB_LYT_TOP) { + strcpy(layer_id, "layer_topsilk"); + } + else { + strcpy(layer_id, "layer_bottomsilk"); + } + group_data[group].exp = 1; + } + else { + if (!group_data[group].draw) + return 0; + scaled_layer_thickness = (group_data[group].solder + || group_data[group].component) ? OUTER_COPPER_THICKNESS : INNER_COPPER_THICKNESS; + sprintf(layer_id, "layer_%02ld", group); + if (!outline_layer) { + group_data[group].exp = 1; + } + } + } + else { + if (flags & PCB_LYT_PDRILL) { + drill_layer = 1; + strcpy(layer_id, "layer_pdrill"); + } + else if (flags & PCB_LYT_UDRILL) { + drill_layer = 1; + strcpy(layer_id, "layer_udrill"); + } + else if (flags & PCB_LYT_MASK) { + if (opt_mask_color == SCAD_MASK_NONE || opt_outline_type == SCAD_OUTLINE_NONE) + return 0; + scaled_layer_thickness = MASK_THICKNESS * 2.; + if ((flags & PCB_LYT_TOP)) { + strcpy(layer_id, "layer_topmask"); + } + else { + strcpy(layer_id, "layer_bottommask"); + } + } + else + return 0; + } + + layer_open = 1; + + if (!outline_layer) { + char tmp_ln[PCB_PATH_MAX]; + const char *name = pcb_layer_to_file_name(tmp_ln, layer, flags, PCB_FNS_fixed); + fprintf(scad_output, "// START_OF_LAYER: %s\n", name); + if (drill_layer) { + fprintf(scad_output, "%s_list=[\n", layer_id); + } + else { + fprintf(scad_output, "module %s_body (offset) {\ntranslate ([0, 0, offset]) union () {\n", layer_id); + } + } + return 1; +} + +static pcb_hid_gc_t scad_make_gc(void) +{ + pcb_hid_gc_t rv = (pcb_hid_gc_t) calloc(1, sizeof(hid_gc_s)); + rv->cap = Trace_Cap; + rv->seq = lastseq++; + return rv; +} + +static void scad_destroy_gc(pcb_hid_gc_t gc) +{ + free(gc); +} + +static void scad_use_mask(pcb_mask_op_t use_it) +{ + current_mask = use_it; +} + +static void scad_set_color(pcb_hid_gc_t gc, const char *name) +{ + if (strcmp(name, "erase") == 0) { + gc->erase = 1; + gc->drill = 0; + } + else if (strcmp(name, "drill") == 0) { + gc->erase = 0; + gc->drill = 1; + } + else { + if (name[0] == '#') { + unsigned int r, g, b; + if (sscanf(name + 1, "%02x%02x%02x", &r, &g, &b) != 3) + pcb_message(PCB_MSG_ERROR, "Invalid color format: %s\n", name); + gc->r = r; + gc->g = g; + gc->b = b; + } + else { + gc->r = 1; + gc->g = 1; + gc->b = 1; + } + gc->erase = 0; + gc->drill = 0; + } +} + +static void scad_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + gc->cap = style; +} + +static void scad_set_line_width(pcb_hid_gc_t gc, pcb_coord_t width) +{ + gc->width = width; +} + +static void scad_set_draw_xor(pcb_hid_gc_t gc, int xor) +{ +} + + +static void scad_draw_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; + scad_fill_polygon(gc, 5, x, y); +} + +/* Helper function - draws the line or collects the line segments +* - on outline layer the line segments are collected and later used to draw board outline +* - otherwise it is drawn as rotated box with circle at the end(s), depending on mode: +* -- on single line segment or last polyline segment caps are drawn on both ends +* -- on polyline segment cap is drawn only on beginning +*/ + +static void scad_emit_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2, int mode) +{ + int zero_length; + float angle = 0., length = 0.; + float cx, cy; + int bd = 0, c1 = 0, c2 = 0; + + if (outline_layer) { + add_outline_segment(x1, y1, x2, y2); + return; + } + + + + zero_length = (x1 == x2 && y1 == y2 && gc->cap != Square_Cap) ? 1 : 0; + + cx = ((float) (x1 + x2)) / 2.; + cy = ((float) (y1 + y2)) / 2.; + + + if (!zero_length) { + angle = -(atan2(-(float) (y2 - y1), -(float) (x2 - x1))) / M_PI * 180.; + length = sqrt((float) (x2 - x1) * (float) (x2 - x1) + (float) (y2 - y1) * (float) (y2 - y1)); + if (gc->cap == Square_Cap) { + length += (float) gc->width; + } + } + + + if (!zero_length) { + bd = 1; + } + if (gc->cap == Trace_Cap || gc->cap == Round_Cap || mode == SCAD_EL_LASTPOLY || mode == SCAD_EL_POLY) { + c2 = 1; + if (!zero_length && (mode != SCAD_EL_POLY)) { + c1 = 1; + } + } + + if (c1 || c2) { + fprintf(scad_output, "\tline_segment_r(%f,%f,%f,%f,%f,%f,%d,%d,%d);\n", + scad_scale_coord(length), + scad_scale_coord((float) gc->width), scaled_layer_thickness, + scad_scale_coord(cx), scad_scale_coord(-cy), angle, bd, c1, c2); + } + else { + if (bd) + fprintf(scad_output, "\tline_segment(%f,%f,%f,%f,%f,%f);\n", + scad_scale_coord(length), + scad_scale_coord((float) gc->width), scaled_layer_thickness, scad_scale_coord(cx), scad_scale_coord(-cy), angle); + } + +} + +static void scad_draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + if (drill_layer) + return; + + scad_emit_line(gc, x1, y1, x2, y2, SCAD_EL_STANDARD); +} + + +static void scad_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) +{ + int i, n_steps, x, y, ox = 0, oy = 0, sa; + float angle; + + if (drill_layer) + return; + + n_steps = ((delta_angle < 0) ? (-delta_angle) : delta_angle + 4) / 5; + sa = start_angle + 180; + if (sa > 360) + sa -= 360; + + for (i = 0; i <= n_steps; i++) { + + angle = ((float) (sa) + ((float) delta_angle * (float) i / (float) n_steps)) * M_PI / 180.; + + if (i) { + x = (int) ((float) width * cos(angle)) + cx; + y = -(int) ((float) height * sin(angle)) + cy; + scad_emit_line(gc, ox, oy, x, y, (i == (n_steps)) ? SCAD_EL_LASTPOLY : SCAD_EL_POLY); + + ox = x; + oy = y; + } + else { + ox = (int) ((float) width * cos(angle)) + cx; + oy = -(int) ((float) height * sin(angle)) + cy; + } + } +} + + +/* Emit the cylinder - its appearance depends on layer it is located on: +* - as plated or unplated drills it creates vector of holes +* - otherwise it is drawn as simple +*/ +static void scad_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ +/* int i; */ + if (outline_layer) + return; + + if (drill_layer && !gc->drill) { + return; + } + if (!drill_layer && gc->drill) { + return; + } + + if (radius <= 0) + return; + + if (drill_layer && ((2 * radius) < opt_minimal_drill)) + return; + + if (drill_layer) { + fprintf(scad_output, "\t[%f, [%f, %f]],\n", scad_scale_coord((float) radius), scad_scale_coord(cx), -scad_scale_coord(cy)); + } + else { + fprintf(scad_output, + "\ttranslate ([%f, %f, 0]) cylinder (r=%f, h=%f, center=true, $fn=30);\n", + scad_scale_coord((float) cx), -scad_scale_coord((float) cy), + scad_scale_coord((float) radius), scaled_layer_thickness); + } +} + +/* +* Helper function - creates extruded polygon +*/ + +static void scad_emit_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y, float thickness) +{ + int i, n; +/* int cw, cx; */ + + + fprintf(scad_output, "\ttranslate ([0, 0, %f]) linear_extrude(height=%f) polygon ([", -thickness / 2., thickness); + + +/* Normalize polygon - remove last point, if it is equal to first point */ + + n = n_coords; + if (x[n_coords - 1] == x[0] && y[n_coords - 1] == y[0]) + n--; + +/* Polygon points*/ + + for (i = 0; i < n; i++) { + fprintf(scad_output, "\t\t[%f, %f]%s\n", + scad_scale_coord((float) x[i]), -scad_scale_coord((float) y[i]), (i < (n - 1)) ? ", " : ""); + } + + fprintf(scad_output, "\t],[[\n\t\t"); + + for (i = 0; i < n; i++) { + if (!(i % 10) && i) + fprintf(scad_output, "\n\t\t"); + fprintf(scad_output, "%d%s", i, (i < (n - 1)) ? ", " : ""); + } + fprintf(scad_output, "]]);\n"); + +} + +static void scad_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + if (outline_layer) + return; + + scad_emit_polygon(gc, n_coords, x, y, scaled_layer_thickness); +} + +static void scad_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]; + + if (scad_output) + fprintf(scad_output, "// Fill rect\n"); + + 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; + scad_fill_polygon(gc, 5, x, y); +} + +static void scad_calibrate(double xval, double yval) +{ + fprintf(stderr, "HID error: pcb called unimplemented openscad function scad_calibrate.\n"); + abort(); +} + +static void scad_set_crosshair(int x, int y, int action) +{ + if (scad_output) + fprintf(scad_output, "// Set CrossHair\n"); +} + +static const char *openscad_cookie = "openscad exporter"; + +static pcb_hid_t scad_hid; + +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); +} + +int pplg_init_export_openscad(void) +{ + memset(&scad_hid, 0, sizeof(scad_hid)); + + pcb_hid_nogui_init(&scad_hid); + pcb_dhlp_draw_helpers_init(&scad_hid); + + scad_hid.struct_size = sizeof(scad_hid); + scad_hid.name = "openscad"; + scad_hid.description = "OpenSCAD script export"; + scad_hid.exporter = 1; + + scad_hid.get_export_options = scad_get_export_options; + scad_hid.do_export = scad_do_export; + scad_hid.parse_arguments = scad_parse_arguments; + scad_hid.set_layer_group = scad_set_layer_group; + scad_hid.calibrate = scad_calibrate; + scad_hid.set_crosshair = scad_set_crosshair; + + scad_hid.make_gc = scad_make_gc; + scad_hid.destroy_gc = scad_destroy_gc; + scad_hid.use_mask = scad_use_mask; + scad_hid.set_color = scad_set_color; + scad_hid.set_line_cap = scad_set_line_cap; + scad_hid.set_line_width = scad_set_line_width; + scad_hid.set_draw_xor = scad_set_draw_xor; + + scad_hid.draw_line = scad_draw_line; + scad_hid.draw_arc = scad_draw_arc; + scad_hid.draw_rect = scad_draw_rect; + scad_hid.fill_circle = scad_fill_circle; + scad_hid.fill_polygon = scad_fill_polygon; + scad_hid.fill_rect = scad_fill_rect; + + pcb_hid_register_hid(&scad_hid); + + pcb_hid_register_attributes(scad_options, sizeof(scad_options) / sizeof(scad_options[0]), openscad_cookie, 0); + return 0; +} Index: tags/1.2.3/src_plugins/export_openscad/scad.h =================================================================== --- tags/1.2.3/src_plugins/export_openscad/scad.h (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/scad.h (revision 8969) @@ -0,0 +1,137 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * OpenSCAD export HID + * This code is based on the GERBER and VRML 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef __SCAD_H +#define __SCAD_H + +#define SCAD_EXT ".scad" +#define SCAD_STL_EXT ".stl" + +/* +#define SCAD_MAP_EXT ".3dm" +#define SCAD_FPMAP_EXT ".fp.3dm" +*/ + +#define MODELBASE "models" +#define SCADBASE "scad" +#define SCADSCRIPTS "scripts" +#define SCADSIMPLEMODELS "simple" + + +/* dimensions (nanometer version) and colors*/ +#define METRIC_SCALE 0.000001 + +#define SCAD_MIN_OUTLINE_DIST 100000 + +#define BOARD_THICKNESS 1.6 +#define OUTER_COPPER_THICKNESS 0.035 +#define INNER_COPPER_THICKNESS (OUTER_COPPER_THICKNESS / 2.) +#define MASK_THICKNESS (OUTER_COPPER_THICKNESS + 0.02 ) +#define SILK_LAYER_THICKNESS ( OUTER_COPPER_THICKNESS + 0.0025 ) +#define SILK_LAYER_OFFSET ( ( BOARD_THICKNESS + SILK_LAYER_THICKNESS ) / 2. ) +#define SILK_LAYER_OFFSET2 ( ( BOARD_THICKNESS + SILK_LAYER_THICKNESS ) / 2. + MASK_THICKNESS) +#define HOLE_THICKNESS ( BOARD_THICKNESS + 2. * OUTER_COPPER_THICKNESS + 0.1) +#define PLATING_THICKNESS ( BOARD_THICKNESS + 2. * OUTER_COPPER_THICKNESS) +#define HOLE_PLATING 0.0175 + +#define SCAD_BOARD_COLOR "[0.44, 0.44, 0]" +#define SCAD_SILK_COLOR "[1, 1, 1]" +#define SCAD_COPPER_COLOR "[1, 0.4, 0.2]" +#define SCAD_COPPER_COLOR_TIN "[0.76, 0.76, 0.76]" +#define SCAD_COPPER_COLOR_GOLD "[1, 0.85, 0.24]" +#define SCAD_MASK_COLOR_G "[0, 0.4, 0.2, 0.65]" +#define SCAD_MASK_COLOR_R "[0.8, 0.1, 0.1, 0.65]" +#define SCAD_MASK_COLOR_B "[0.1, 0.1, 0.8, 0.65]" + + +#define SCAD_COMPONENT_NONE 0 +#define SCAD_COMPONENT_BOXES 1 +#define SCAD_COMPONENT_SIMPLE 2 +#define SCAD_COMPONENT_REALISTIC 3 + +#define EXPORT_COMPONENTS ((opt_exp_component == SCAD_COMPONENT_BOXES) || (opt_exp_component == SCAD_COMPONENT_SIMPLE) || (opt_exp_component == SCAD_COMPONENT_REALISTIC)) + +#define SCAD_OUTLINE_NONE 0 +#define SCAD_OUTLINE_OUTLINE 1 +#define SCAD_OUTLINE_SIZE 2 + +#define SCAD_COPPER_COPPER 0 +#define SCAD_COPPER_GOLD 1 +#define SCAD_COPPER_TIN 2 + +#define SCAD_MASK_NONE 0 +#define SCAD_MASK_GREEN 1 +#define SCAD_MASK_BLUE 2 +#define SCAD_MASK_RED 3 + +#define SCAD_CUT_COMPLETE 0 +#define SCAD_CUT_TOP 1 +#define SCAD_CUT_TOP_ONLY 2 +#define SCAD_CUT_BOTTOM 3 +#define SCAD_CUT_BOTTOM_ONLY 4 + +#define MAX_LAYER_COLORS (PCB_MAX_LAYER *2) + +/* polygon attributes */ + +#define POLY_CW 1 +#define POLY_CCW 2 + +#define POLY_CONVEX 1 +#define POLY_CONCAVE 2 + +#define SCAD_EL_STANDARD 0 +#define SCAD_EL_POLY 1 +#define SCAD_EL_LASTPOLY 2 + +typedef struct color_table_struct { + int r, g, b; +} color_table_struct; + +typedef struct hid_gc_s { + pcb_cap_style_t cap; + int width; + int erase; + int drill; + int r, g, b; + int seq; +} hid_gc_s; + +typedef struct { + int processed; + pcb_coord_t x1, y1, x2, y2; +} t_outline_segment; + +extern FILE *scad_output; + +extern void scad_write_prologue(); +extern void scad_generate_holes(); +extern void scad_generate_plating(); +extern void scad_generate_board(); +extern void scad_generate_mask(); +extern float scad_scale_coord(float x); + +void scad_process_components(int mode); + +#endif Index: tags/1.2.3/src_plugins/export_openscad/scadcomp.c =================================================================== --- tags/1.2.3/src_plugins/export_openscad/scadcomp.c (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/scadcomp.c (revision 8969) @@ -0,0 +1,554 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * OpenSCAD export HID + * This code is based on the GERBER and VRML 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "board.h" +#include "data.h" +#include "error.h" +#include "buffer.h" +#include "misc_util.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "hid_init.h" + +#include "scad.h" + +/* model types for scad_export_model */ +#define SCAD_STANDARD 0 /* primary model */ +#define SCAD_OVERLAY 1 + + +static char *include_files_list; +static int include_files_size, include_files_bufsize, include_file_maxlength; + +static void scad_init_include_files(void) +{ + include_files_list = NULL; + include_files_size = 0; + include_files_bufsize = 0; + include_file_maxlength = 0; +} + +static void scad_free_include_files(void) +{ + if (include_files_list) + free(include_files_list); +} + +static void scad_add_include_file(char *include_file) +{ + + int ln = strlen(include_file); + int new_length = ln + include_files_size + 1; + int ptr; + char *bf; + +/* quietly assumimng, that include file name is shorter than 2048 characters */ + if (!include_files_list || (include_files_list != NULL && new_length > include_files_bufsize)) { + bf = malloc(2048 + include_files_bufsize); + if (bf) { + include_files_list = bf; + include_files_size = 0; + include_files_bufsize = 2048; + } + else { + pcb_message(PCB_MSG_ERROR, "openscad: cannot allocate memory for component included files.\n"); + } + } + +/* Check, if the file is already in list */ + ptr = 0; + while (ptr < include_files_size) { + if (strcmp(include_files_list + ptr, include_file) == 0) { + return; + } + ptr += strlen(include_files_list + ptr) + 1; + } + strcpy(include_files_list + ptr, include_file); + include_files_size = new_length; + if (ln > include_file_maxlength) { + include_file_maxlength = ln; + } +} + +static void scad_export_include_files(void) +{ + int ptr; + char *fullname; + char line[2048]; + int l; + FILE *f; +#warning TODO: no libdir + char *pcblibdir = "TODO_libdir63"; + + if (!include_files_list) + return; + + l = strlen(pcblibdir) + 1 + strlen(MODELBASE) + 1 + strlen(SCADBASE) + 1 + include_file_maxlength + 1; + if ((fullname = (char *) malloc(l * sizeof(char))) == NULL) { + pcb_message(PCB_MSG_ERROR, "openscad: cannot allocate memory for component included files.\n"); + return; + } + sprintf(fullname, "%s%s%s%s%s%s", pcblibdir, PCB_DIR_SEPARATOR_S, + MODELBASE, PCB_DIR_SEPARATOR_S, SCADBASE, PCB_DIR_SEPARATOR_S); + + l = strlen(fullname); /* index to be used to append include file names */ + + fprintf(scad_output, "/***************************************************/\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/* Embedded include files */\n"); + fprintf(scad_output, "/* */\n"); + fprintf(scad_output, "/***************************************************/\n"); + + ptr = 0; + while (ptr < include_files_size) { + strcpy(fullname + l, include_files_list + ptr); + /* printf ("[%s] @ %s\n", include_files_list + ptr, fullname); */ + f = fopen(fullname, "r"); + if (f) { + while (fgets(line, sizeof(line), f)) { + fputs(line, scad_output); + } + fclose(f); + } + else { + fprintf(scad_output, "include <%s>\n", include_files_list + ptr); + } + + ptr += strlen(include_files_list + ptr) + 1; + } + fprintf(scad_output, "\n"); + +} + + +/*********************************************************************** +* +* Export of the components +* +***********************************************************************/ +static void scad_imported_model_name(char *model, char *name, int size, pcb_bool simple) +{ + + sprintf(name, "%s%s%s%s", model, (simple) ? "-" : "", (simple) ? SCADSIMPLEMODELS : "", SCAD_STL_EXT); +} + +static void scad_close_model(FILE * f) +{ + if (f) { + fclose(f); + } +} + +static FILE *scad_open_model(char *model, char *first_line, int size, pcb_bool simple) +{ + int l; + FILE *f = NULL; + char *cmd; +#warning TODO: no libdir + char *pcblibdir = "TODO_libdir63"; + + l = + strlen(pcblibdir) + 1 + strlen(MODELBASE) + 1 + strlen(SCADBASE) + 1 + + strlen(SCADSIMPLEMODELS) + 1 + strlen(model) + 1 + strlen(SCAD_EXT); + if ((cmd = (char *) malloc(l * sizeof(char))) != NULL) { + sprintf(cmd, "%s%s%s%s%s%s%s%s%s%s", pcblibdir, PCB_DIR_SEPARATOR_S, + MODELBASE, PCB_DIR_SEPARATOR_S, SCADBASE, PCB_DIR_SEPARATOR_S, + model, (simple) ? "-" : "", (simple) ? SCADSIMPLEMODELS : "", SCAD_EXT); + + f = fopen(cmd, "r"); +#if 0 + if (!f) { + sprintf(cmd, "%s%s%s%s%s%s%s%s%s%s", pcblibdir, + PCB_DIR_SEPARATOR_S, MODELBASE, PCB_DIR_SEPARATOR_S, + SCADBASE, PCB_DIR_SEPARATOR_S, + (simple) ? SCADSIMPLEMODELS : "", (simple) ? PCB_DIR_SEPARATOR_S : "", model, SCAD_EXT); + f = fopen(cmd, "r"); + } +#endif + } + + if (cmd) + free(cmd); + + if (f && fgets(first_line, size, f)) + return f; + + if (f) + scad_close_model(f); + + return NULL; + +} + +static void scad_process_line(char *line) +{ + char *s0, *s1, *s2; + + if ((s0 = strstr(line, "include")) != NULL && (s1 = strchr(s0, '<')) != NULL && (s2 = strchr(s1, '>')) != NULL) { + *s2 = 0; + scad_add_include_file(s1 + 1); + } + else { + fputs(line, scad_output); + } +} + + +static int scad_parse_coord_triplet(char *s, pcb_coord_t * ox, pcb_coord_t * oy, pcb_coord_t * oz) +{ + pcb_coord_t xx = 0, yy = 0, zz = 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; + case 2: + zz = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + } + s = s + ln; + n++; + } + if (n == 3) { + *ox = xx; + *oy = yy; + *oz = zz; + return pcb_true; + } + else { + return pcb_false; + } +} + +static int scad_parse_float_triplet(char *s, float *ox, float *oy, float *oz) +{ + float xx = 0, yy = 0, zz = 0; + + if (sscanf(s, "%f %f %f", &xx, &yy, &zz) == 3) { + *ox = xx; + *oy = yy; + *oz = zz; + return pcb_true; + } + else { + return pcb_false; + } +} + +/************************************************************ +* Export of the single model +* - adjusts the model position, rotation, scale +* - processes the model line-by-line and perfoprms variable expansion +************************************************************/ +static void scad_export_model(int model_type, pcb_element_t * element, pcb_bool imported, FILE * f, char *line, int size) +{ + char *model_rotation, *model_translate, *model_scale, *model_angle; + pcb_angle_t tmp_angle = (pcb_angle_t) 0; + pcb_coord_t tx, ty, tz; + float fx, fy, fz; + + int x = element->MarkX, y = element->MarkY; + + model_rotation = + pcb_attribute_get(&(element->Attributes), + (model_type == SCAD_OVERLAY) ? "OpenSCAD::Overlay:rotate" : "OpenSCAD::Model:rotate"); + model_scale = + pcb_attribute_get(&(element->Attributes), + (model_type == SCAD_OVERLAY) ? "OpenSCAD::Overlay:scale" : "OpenSCAD::Model:scale"); + model_translate = + pcb_attribute_get(&(element->Attributes), + (model_type == SCAD_OVERLAY) ? "OpenSCAD::Overlay:translate" : "OpenSCAD::Model:translate"); + + if ((model_angle = pcb_attribute_get(&(element->Attributes), "Footprint::RotationTracking")) != NULL) { + sscanf(model_angle, "%lf", &tmp_angle); + } + + if (model_translate && scad_parse_coord_triplet(model_translate, &tx, &ty, &tz)) + fprintf(scad_output, "translate ([%f, %f, %f]) ", scad_scale_coord(tx), scad_scale_coord(ty), scad_scale_coord(tz)); + + fprintf(scad_output, "translate ([%f, %f, %f]) ", + scad_scale_coord((float) x), -scad_scale_coord((float) y), + ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) ? -1. : 1.) * (BOARD_THICKNESS / 2. + OUTER_COPPER_THICKNESS)); + + /* rotate order: angle onsolder user-defined */ + if (tmp_angle != 0.) + fprintf(scad_output, "rotate ([0, 0, %f]) ", (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) ? -tmp_angle : tmp_angle); + + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) + fprintf(scad_output, "rotate([180.,0,0]) "); + + if (model_rotation && scad_parse_float_triplet(model_rotation, &fx, &fy, &fz)) + fprintf(scad_output, "rotate ([%f, %f, %f]) ", fx, fy, fz); + + if (model_scale && scad_parse_float_triplet(model_scale, &fx, &fy, &fz)) + fprintf(scad_output, "scale ([%f, %f, %f]) ", fx, fy, fz); + + if (imported) { + fprintf(scad_output, "{ import(\"%s\"); }\n", line); + + } + else { + fprintf(scad_output, "{\n"); + + /* Flush first line of text, already read in buffer */ + scad_process_line(line); + + while (fgets(line, size, f)) { + scad_process_line(line); + } + fprintf(scad_output, "}\n"); + } +} + + + +extern void pcb_buffer_free_rotate(pcb_buffer_t * Buffer, pcb_angle_t angle); + +static int scad_calculate_bbox(pcb_element_t * element, pcb_angle_t angle, float *w, float *h, float *ox, float *oy) +{ + return 0; + +/* + TODO: automatic calculation of bounding box + + pcb_buffer_t element_buffer; + + element_buffer.Data = pcb_buffer_new(); + + -- Copy + AddElementToBuffer (pcb_element_t *Element) + if (PCB_ON_SIDE(Element,(Settings.ShowBottomSide)?BOTTOM_SIDE:TOP_SIDE)) + pcb_element_mirror(element_buffer.Data, element, 0); + + pcb_buffer_clear(PCB, &element_buffer); +*/ +} + +/************************************************************ +* Export of the single element +* - identifies the model for the component - primary and overlay +* - exports both models +************************************************************/ +static void scad_export_bbox(pcb_element_t * element) +{ + char *model_angle, *bbox; + pcb_angle_t tmp_angle = (pcb_angle_t) 0; + float w = 0., h = 0., t = 0., ox = 0., oy = 0.; + int x = element->MarkX, y = element->MarkY; + int n, ln; + char val[32], *s; + + if ((bbox = pcb_attribute_get(&(element->Attributes), "Footprint::BoundingBox")) == NULL) + return; + + + if ((model_angle = pcb_attribute_get(&(element->Attributes), "Footprint::RotationTracking")) != NULL) { + sscanf(model_angle, "%lf", &tmp_angle); + } + + /* Parse values with units... */ + s = bbox; + n = 0; + while (sscanf(s, "%30s%n", val, &ln) >= 1) { + switch (n) { + case 0: + w = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + case 1: + h = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + case 2: + t = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + case 3: + ox = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + case 4: + oy = pcb_get_value_ex(val, NULL, NULL, NULL, "mm", NULL); + break; + } + s = s + ln; + n++; + } + + if (n == 3) { + ox = 0.; + oy = 0.; + } + else if (n == 1) { + /* Try automatically calculate the bounding box */ + t = w; + if (!scad_calculate_bbox(element, tmp_angle, &w, &h, &ox, &oy)) + return; + } + else if (n != 5) + return; + + fprintf(scad_output, "translate ([%f, %f, %f]) ", + scad_scale_coord((float) x), -scad_scale_coord((float) y), + ((PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) ? -1. : 1.) * (BOARD_THICKNESS / 2. + OUTER_COPPER_THICKNESS)); + + if (tmp_angle != 0.) + fprintf(scad_output, "rotate ([0, 0, %f]) ", (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) ? -tmp_angle : tmp_angle); + if (PCB_FLAG_TEST(PCB_FLAG_ONSOLDER, (element))) + fprintf(scad_output, "rotate([180.,0,0]) "); + + fprintf(scad_output, "{\n"); + + fprintf(scad_output, + "translate ([%f, %f, %f]) color ([0.2, 0.2, 0.2]) cube ([%f,%f,%f],true);\n", + scad_scale_coord((float) ox), scad_scale_coord((float) oy), + scad_scale_coord((float) t / 2.), scad_scale_coord((float) w), + scad_scale_coord((float) h), scad_scale_coord((float) t)); + + fprintf(scad_output, "}\n"); + +} + +static void scad_writeout_element(pcb_element_t * element, char *name, int model_type, pcb_bool imported, pcb_bool simple) +{ + FILE *f = NULL; + char line[2048]; + + if (imported) { + scad_imported_model_name(name, line, sizeof(line), simple); + scad_export_model(model_type, element, imported, f, line, sizeof(line)); + } + else { + /* if model is defined, try to open it */ + f = scad_open_model(name, line, sizeof(line), simple); + + if (f) { + scad_export_model(model_type, element, imported, f, line, sizeof(line)); + scad_close_model(f); + } + } +} + +/************************************************************ +* Export of the single element +* - identifies the model for the component - primary and overlay +* - exports both models +************************************************************/ +static void scad_export_element(pcb_element_t * element, pcb_bool simple) +{ + char *model_name, *s; + pcb_bool imported_model; + + s = pcb_attribute_get(&(element->Attributes), "OpenSCAD::Model:type"); + imported_model = s && (strcmp(s, "STL") == 0); + + /* get model name from attibute */ + model_name = pcb_attribute_get(&(element->Attributes), "OpenSCAD::Model"); + + if (model_name) { + scad_writeout_element(element, model_name, SCAD_STANDARD, imported_model, simple); + } + else { + /* no model variable found, try model, based on footprint name attribute */ + model_name = pcb_attribute_get(&(element->Attributes), "Footprint::File"); + if (model_name) { + scad_writeout_element(element, model_name, SCAD_STANDARD, imported_model, simple); + } + else { + /* still no model found, try model, based on description */ + model_name = PCB_ELEM_NAME_DESCRIPTION(element); + if (model_name) { + scad_writeout_element(element, model_name, SCAD_STANDARD, imported_model, simple); + } + } + } + + s = pcb_attribute_get(&(element->Attributes), "OpenSCAD::Overlay:type"); + imported_model = s && (strcmp(s, "STL") == 0); + + /* get overlay name from attibute */ + model_name = pcb_attribute_get(&(element->Attributes), "OpenSCAD::Overlay"); + + if (model_name) { + scad_writeout_element(element, model_name, SCAD_OVERLAY, imported_model, simple); + } + + return; +} + +/************************************************************ +* Main function for components export +* - initialize footprint and element database +* - loops through all components on the board and for each component: +* - loads the footprint into temporary buffer and calculates anfgle +* - export the element +************************************************************/ +void scad_process_components(int mode) +{ + + scad_init_include_files(); + + + fprintf(scad_output, "module all_components() {\n"); + + + PCB_ELEMENT_LOOP(PCB->Data); + { + if ((mode == SCAD_COMPONENT_SIMPLE) || (mode == SCAD_COMPONENT_REALISTIC)) { + scad_export_element(element, (mode == SCAD_COMPONENT_SIMPLE) ? 1 : 0); + } + else { + scad_export_bbox(element); + } + } + + PCB_END_LOOP; + + fprintf(scad_output, "}\n\n"); + + scad_export_include_files(); + + scad_free_include_files(); + +} Index: tags/1.2.3/src_plugins/export_openscad/scadproto.c =================================================================== --- tags/1.2.3/src_plugins/export_openscad/scadproto.c (nonexistent) +++ tags/1.2.3/src_plugins/export_openscad/scadproto.c (revision 8969) @@ -0,0 +1,113 @@ +/* + * COPYRIGHT + * + * PCB, interactive printed circuit board design + * + * OpenSCAD export HID + * This code is based on the GERBER and VRML 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "data.h" +#include "error.h" +#include "buffer.h" + +#include "hid.h" +#include "hid_nogui.h" +#include "hid_draw_helpers.h" +#include "hid_init.h" + +#include "scad.h" + + +void scad_write_prologue() +{ + fputs("//SCAD\n\n", scad_output); + + fputs + ("module line_segment_r(length, width, thickness, x, y, a, bd, c1, c2) {\n" + "\ttranslate([x,y,0]) rotate ([0,0,a]) union() {\n" + "\t\tif (bd) {cube ([length, width,thickness],true);}\n" + "\t\tif (c2) {translate([length/2.,0,0]) cylinder(h=thickness, r=width/2,center=true,$fn=30);}\n" + "\t\tif (c1) { translate([-length/2.,0,0]) cylinder(h=thickness, r=width/2,center=true,$fn=30);}\n" + "\t}\n" "}\n\n", scad_output); + + fputs("module line_segment(length, width, thickness, x, y, a) {\n" + "\ttranslate([x,y,0]) rotate ([0,0,a]) {\n" + "\t\tcube ([length, width,thickness],true);\n" "\t}\n" "}\n\n", scad_output); +} + +void scad_generate_holes() +{ + fprintf(scad_output, "module all_holes() {\n\tplating=%f;\n", HOLE_PLATING); + fprintf(scad_output, "\tunion () {\n"); + fprintf(scad_output, "\t\tfor (i = layer_pdrill_list) {\n"); + fprintf(scad_output, + "\t\t\ttranslate([i[1][0],i[1][1],0]) cylinder(r=i[0]+2*plating, h=%f, center=true, $fn=30);\n", HOLE_THICKNESS); + fprintf(scad_output, "\t\t}\n"); + fprintf(scad_output, "\t\tfor (i = layer_udrill_list) {\n"); + fprintf(scad_output, "\t\t\ttranslate([i[1][0],i[1][1],0]) cylinder(r=i[0], h=%f, center=true, $fn=30);\n", HOLE_THICKNESS); + fprintf(scad_output, "\t\t}\n"); + fprintf(scad_output, "\t}\n"); + fprintf(scad_output, "}\n\n"); +} + +void scad_generate_plating() +{ + fprintf(scad_output, "module all_plating() {\n"); + fprintf(scad_output, "\tplating=%f;\n", HOLE_PLATING + 0.02); + fprintf(scad_output, "\tunion () {\n"); + fprintf(scad_output, "\t\tfor (i = layer_pdrill_list) {\n"); + fprintf(scad_output, "\t\t\ttranslate([i[1][0],i[1][1],0]) difference () {\n"); + fprintf(scad_output, "\t\t\t\tcylinder(r=i[0]+2*plating, h=%f, center=true, $fn=30);\n", PLATING_THICKNESS + 0.01); + fprintf(scad_output, "\t\t\t\tcylinder(r=i[0]-0.01, h=%f, center=true, $fn=30);\n", PLATING_THICKNESS + 0.2); + fprintf(scad_output, "\t\t\t}\n"); + fprintf(scad_output, "\t\t}\n"); + fprintf(scad_output, "\t}\n"); + fprintf(scad_output, "}\n\n"); +} + +void scad_generate_board() +{ + fprintf(scad_output, "module board_body() {\n"); + fprintf(scad_output, + "\ttranslate ([0, 0, %f]) linear_extrude(height=%f) board_outline();", -BOARD_THICKNESS / 2., BOARD_THICKNESS); + fprintf(scad_output, "}\n\n"); +} + +void scad_generate_mask() +{ + fprintf(scad_output, "module mask_surface() {\n"); + fprintf(scad_output, + "\ttranslate ([0, 0, %f]) linear_extrude(height=%f) board_outline();", -MASK_THICKNESS / 2., MASK_THICKNESS); + fprintf(scad_output, "}\n\n"); +} Index: tags/1.2.3/src_plugins/export_png/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_png/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_png/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_png + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_png/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_png/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_png/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_png/export_png.pup =================================================================== --- tags/1.2.3/src_plugins/export_png/export_png.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_png/export_png.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short png/gif/jpg pcb_exporter +$long Export to png, gif and jpeg +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_png/png.c =================================================================== --- tags/1.2.3/src_plugins/export_png/png.c (nonexistent) +++ tags/1.2.3/src_plugins/export_png/png.c (revision 8969) @@ -0,0 +1,1728 @@ + /* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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, mask_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); + 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); /* 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, 20, 1}, + {10, 0, -10}, + {-1, -20, -1}, +}; + +static int shadows[5][5] = { + {1, 1, 1, 1, -1}, + {1, 1, 1, -1, -1}, + {1, 1, 0, -1, -1}, + {1, -1, -1, -1, -1}, + {-1, -1, -1, -1, -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_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; + + if (color_cache) { + free(color_cache); + color_cache = NULL; + } + + if (brush_cache) { + free(brush_cache); + brush_cache = NULL; + } + + 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); + 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 = fopen(filename, "wb"); + if (!f) { + perror(filename); + return; + } + + 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; + 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; + + if (photo_copper[photo_groups[1]] + && gdImageGetPixel(photo_copper[photo_groups[1]], x, y)) + rgb(&cop, 40, 40, 40); + else + rgb(&cop, 100, 100, 110); + + if (photo_ngroups == 2) + 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); + + gdImageDestroy(im); +} + +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) malloc(sizeof(hid_gc_s)); + 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 int mask_op = 0; +static void png_use_mask(pcb_mask_op_t use_it) +{ + if (photo_mode) + return; + + switch(use_it) { + case HID_MASK_OFF: + mask_op = 0; + break; + + case HID_MASK_BEFORE: + break; + + case HID_MASK_INIT: + if (mask_im == NULL) { + mask_im = gdImageCreate(gdImageSX(im), gdImageSY(im)); + if (!mask_im) { + pcb_message(PCB_MSG_ERROR, "png_use_mask(): gdImageCreate(%d, %d) returned NULL. Corrupt export!\n", gdImageSY(im), gdImageSY(im)); + return; + } + gdImagePaletteCopy(mask_im, im); + } + im = mask_im; + gdImageFilledRectangle(mask_im, 0, 0, gdImageSX(mask_im), gdImageSY(mask_im), white->c); + break; + + case HID_MASK_AFTER: + { + int x, y, c; + im = master_im; + for (x = 0; x < gdImageSX(im); x++) { + for (y = 0; y < gdImageSY(im); y++) { + c = gdImageGetPixel(mask_im, x, y); + if (c) + gdImageSetPixel(im, x, y, c); + } + } + } + + case HID_MASK_CLEAR: + mask_op = HID_MASK_CLEAR; + break; + case HID_MASK_SET: + mask_op = HID_MASK_SET; + 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, "erase") == 0 || 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(master_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 { + printf("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 void use_gc(pcb_hid_gc_t gc) +{ + int need_brush = 0; + color_struct *clr; + + 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; + } + + clr = gc->color; + if (mask_op == HID_MASK_CLEAR) + clr = white; + + need_brush |= (gc->color->r != last_color_r) || (gc->color->g != last_color_g) || (gc->color->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->color->r, gc->color->g, gc->color->b, type, r); + + last_color_r = gc->color->r; + last_color_g = gc->color->g; + last_color_b = gc->color->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; + } + fg = gdImageColorAllocateAlpha(gc->brush, gc->color->r, gc->color->g, gc->color->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(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(im, SCALE_X(x1), SCALE_Y(y1), SCALE_X(x2), SCALE_Y(y2), gc->color->c); +} + +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) +{ + use_gc(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, gc->color->c); + have_outline |= doing_outline; +} + +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) +{ + 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(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 = gdImageColorResolve(im, gc->color->r, gc->color->g, + gc->color->b), 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; + + 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_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; + + use_gc(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_fill_circle(pcb_hid_gc_t gc, pcb_coord_t cx, pcb_coord_t cy, pcb_coord_t radius) +{ + pcb_coord_t my_bloat; + + use_gc(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), gc->color->c); + +} + +static void png_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + 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(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]); + points[i].y = SCALE_Y(y[i]); + } + gdImageSetThickness(im, 0); + linewidth = 0; + gdImageFilledPolygon(im, points, n_coords, gc->color->c); + free(points); +} + +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 foo.pcb [png options]\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_png(int ver_needed) { return 0; } + +void pplg_uninit_export_png(void) +{ +} + +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.poly_before = 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.use_mask = png_use_mask; + 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_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.3/src_plugins/export_png/png.h =================================================================== --- tags/1.2.3/src_plugins/export_png/png.h (nonexistent) +++ tags/1.2.3/src_plugins/export_png/png.h (revision 8969) @@ -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.3/src_plugins/export_ps/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_ps/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_ps + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_ps/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_ps/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_ps/eps.c =================================================================== --- tags/1.2.3/src_plugins/export_ps/eps.c (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/eps.c (revision 8969) @@ -0,0 +1,649 @@ +#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 "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_use_mask(pcb_mask_op_t use_it); +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_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_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); + 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->On) + 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; + } + + if (fast_erase) { + eps_hid.poly_before = 1; + eps_hid.poly_after = 0; + } + else { + eps_hid.poly_before = 0; + eps_hid.poly_after = 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); /* 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 = 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_use_mask(pcb_mask_op_t use_it) +{ + static int mask_pending = 0; + switch (use_it) { + case HID_MASK_CLEAR: + if (!mask_pending) { + mask_pending = 1; + fprintf(f, "gsave\n"); + } + break; + case HID_MASK_AFTER: + case HID_MASK_BEFORE: + case HID_MASK_SET: + break; + case HID_MASK_OFF: + if (mask_pending) { + mask_pending = 0; + 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 (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; + 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); + pcb_fprintf(f, "%ma %ma %mi %mi %mi %mi %g a\n", sa, ea, -width, height, cx, cy, (double) linewidth / width); +} + +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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + 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], y[i], op); + op = "lineto"; + } + fprintf(f, "fill\n"); +} + +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 foo.pcb [eps options]\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.poly_after = 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.use_mask = eps_use_mask; + 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_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.3/src_plugins/export_ps/export_ps.pup =================================================================== --- tags/1.2.3/src_plugins/export_ps/export_ps.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/export_ps.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short postscript pcb_exporter +$long Export postscript or embedded postscript. +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_ps/ps.c =================================================================== --- tags/1.2.3/src_plugins/export_ps/ps.c (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/ps.c (revision 8969) @@ -0,0 +1,1649 @@ +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + +#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 "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, 0, {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, 0, {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_mask_op_t mask_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 %mi %mi 0 \"\" \"\"\n", + media_data[global.media_idx].name, + 72 * media_data[global.media_idx].Width, 72 * 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 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 = 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_LYT_OUTLINE, &lid, 1); + if (lid >= 0) + global.outline_layer = pcb_get_layer(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); /* 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, pcb_coord_t dx, pcb_coord_t 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 %mi %mi 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(layer) && + !(flags & PCB_LYT_OUTLINE)) { + pcb_draw_layer(global.outline_layer, &global.exps.view); + } + + 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_use_mask(pcb_mask_op_t use_it) +{ + global.mask_mode = use_it; +} + +static void ps_set_color(pcb_hid_gc_t gc, const char *name) +{ + if (global.mask_mode == HID_MASK_CLEAR) { + gc->r = gc->g = gc->b = 255; + gc->erase = 0; + } + else if (global.mask_mode == HID_MASK_SET) { + gc->r = gc->g = gc->b = 255; + gc->erase = 1; + } + 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; + if ((width == 0) && (height == 0)) /* degenerate case, do not draw */ + 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); + pcb_fprintf(global.f, "%ma %ma %mi %mi %mi %mi %g a\n", + sa, ea, -width, height, cx, cy, (double) (global.linewidth + 2 * global.bloat) /(double) width); +} + +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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + 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], y[i], op); + op = "lineto"; + } + fprintf(global.f, "fill\n"); +} + +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_polygon_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"))) + return; + + if (use_command || strchr(vals[0].str_value, '|')) { + const char *cmd = vals[0].str_value; + while (*cmd == ' ' || *cmd == '|') + cmd++; + ps_cal_file = popen(cmd, "w"); + used_popen = 1; + } + else + ps_cal_file = 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) + 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->use_mask = ps_use_mask; + 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 = 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 foo.pcb [ps options]\n\n"); + return 0; +} + +static void plugin_ps_uninit(void) +{ + pcb_hid_remove_actions_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.3/src_plugins/export_ps/ps.h =================================================================== --- tags/1.2.3/src_plugins/export_ps/ps.h (nonexistent) +++ tags/1.2.3/src_plugins/export_ps/ps.h (revision 8969) @@ -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.3/src_plugins/export_stat/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_stat/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_stat/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_stat + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_stat/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_stat/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_stat/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_stat/export_stat.pup =================================================================== --- tags/1.2.3/src_plugins/export_stat/export_stat.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_stat/export_stat.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short export board statistics +$long Export various board statistics in lihata format +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_stat/stat.c =================================================================== --- tags/1.2.3/src_plugins/export_stat/stat.c (nonexistent) +++ tags/1.2.3/src_plugins/export_stat/stat.c (revision 8969) @@ -0,0 +1,360 @@ + /* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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]; + time_t t; + 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 = fopen(filename, "w"); + if (!f) { + perror(filename); + return; + } + + pcb_board_count_holes(&hp, &hup, NULL); + t = time(NULL); + strftime(buff, sizeof(buff), "%Y-%m-%d %H:%M:%S", localtime(&t)); + + 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 foo.pcb [stat options]\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.3/src_plugins/export_svg/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_svg/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_svg/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_svg + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_svg/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_svg/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_svg/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_svg/export_svg.pup =================================================================== --- tags/1.2.3/src_plugins/export_svg/export_svg.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_svg/export_svg.pup (revision 8969) @@ -0,0 +1,6 @@ +$class export +$short SVG pcb_exporter +$long Scalable Vector Graphics (SVG) exporter +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/export_svg/svg.c =================================================================== --- tags/1.2.3/src_plugins/export_svg/svg.c (nonexistent) +++ tags/1.2.3/src_plugins/export_svg/svg.c (revision 8969) @@ -0,0 +1,768 @@ + /* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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 "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 erase, drill; +} 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 pcb_mask_op_t mask_mode = HID_MASK_OFF; + +gds_t sbright, sdark, snormal; + +/* Photo mode colors and hacks */ +const char *board_color = "#464646"; +const char *mask_color = "#00ff00"; +float mask_opacity_factor = 0.5; + +enum { + PHOTO_MASK, + PHOTO_SILK, + PHOTO_COPPER, + PHOTO_INNER +} photo_color; + +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); /* 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; + + 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 = 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) malloc(sizeof(hid_gc_s)); + 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_use_mask(pcb_mask_op_t use_it) +{ + mask_mode = use_it; + switch(mask_mode) { + case HID_MASK_INIT: + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n", PCB->MaxWidth, PCB->MaxHeight); + pcb_append_printf(&snormal, "\n", PCB->MaxWidth, PCB->MaxHeight); + break; + + case HID_MASK_OFF: + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n"); + pcb_append_printf(&snormal, "\n", mask_color); + break; + } +} + +static const char *svg_color(pcb_hid_gc_t gc) +{ + if (mask_mode == HID_MASK_SET) + return "#FFFFFF"; + if (mask_mode == HID_MASK_CLEAR) + return "#000000"; + return gc->color; +} + +static void svg_set_color(pcb_hid_gc_t gc, const char *name) +{ + gc->drill = gc->erase = 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) +{ + indent(&snormal); + pcb_append_printf(&snormal, "\n", + x1, y1, w, h, stroke, svg_color(gc), 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) +{ + if ((photo_mode) && (!gc->erase) && (mask_mode == HID_MASK_OFF)) { + 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)); + } +} + +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 draw_line(pcb_hid_gc_t gc, pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + if ((photo_mode) && (!gc->erase) && (mask_mode == HID_MASK_OFF)) { + 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)); + } +} + +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); + draw_line(gc, x1, y1, x2, y2); +} + +static void draw_arc(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) +{ + if ((photo_mode) && (!gc->erase) && (mask_mode == HID_MASK_OFF)) { + 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)); + } +} + +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; + pcb_angle_t sa, ea; + + if (width == 0) /* degenerate case: do not draw r=0 arc, some rendering engines may not like that */ + 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 = cx + (width * cos(sa * M_PI / 180)); + y2 = cy + (width * sin(sa * M_PI / 180)); + x1 = cx + (width * cos(ea * M_PI / 180))+diff; + y1 = cy + (width * sin(ea * M_PI / 180))+diff; + + draw_arc(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) +{ + if ((photo_mode) && (!gc->erase) && (mask_mode == HID_MASK_OFF)) { + 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)); + } +} + +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 offs, 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(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + if ((photo_mode) && (!gc->erase) && (mask_mode == HID_MASK_OFF)) { + pcb_coord_t photo_offs = photo_palette[photo_color].offs; + if (photo_offs != 0) { + draw_poly(&sbright, gc, n_coords, x, y, -photo_offs, photo_palette[photo_color].bright); + draw_poly(&sdark, gc, n_coords, x, y, +photo_offs, photo_palette[photo_color].dark); + } + draw_poly(&snormal, gc, n_coords, x, y, 0, photo_palette[photo_color].normal); + } + else + draw_poly(&snormal, gc, n_coords, x, y, 0, svg_color(gc)); +} + +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 foo.pcb [svg options]\n\n"); + return 0; +} + +#include "dolists.h" + +int pplg_check_ver_export_svg(int ver_needed) { return 0; } + +void pplg_uninit_export_svg(void) +{ +} + +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.use_mask = svg_use_mask; + 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_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.3/src_plugins/export_test/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_test/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_test/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_export_test + + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_test/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_test/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_test/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_test/export_test.c =================================================================== --- tags/1.2.3/src_plugins/export_test/export_test.c (nonexistent) +++ tags/1.2.3/src_plugins/export_test/export_test.c (revision 8969) @@ -0,0 +1,358 @@ +#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) +{ +#if 0 + export_testList *lastb; + StringList *lasts; + char *descr, *value; + + while (export_test != NULL) { + if (fp) { + descr = Cleanexport_testString(export_test->descr); + value = Cleanexport_testString(export_test->value); + fprintf(fp, "%d,\"%s\",\"%s\",", export_test->num, descr, value); + free(descr); + free(value); + } + + while (export_test->refdes != NULL) { + if (fp) { + fprintf(fp, "%s ", export_test->refdes->str); + } + free(export_test->refdes->str); + lasts = export_test->refdes; + export_test->refdes = export_test->refdes->next; + free(lasts); + } + if (fp) { + fprintf(fp, "\n"); + } + lastb = export_test; + export_test = export_test->next; + free(lastb); + } +#endif +} + +static int Printexport_test(void) +{ +#if 0 + char utcTime[64]; + pcb_coord_t x, y; + double theta = 0.0; + double sumx, sumy; + double pin1x = 0.0, pin1y = 0.0, pin1angle = 0.0; + double pin2x = 0.0, pin2y = 0.0; + int found_pin1; + int found_pin2; + int pin_cnt; + time_t currenttime; + FILE *fp; + export_testList *export_test = NULL; + char *name, *descr, *value; + + + fp = fopen(xy_filename, "w"); + if (!fp) { + gui->log("Cannot open file %s for writing\n", xy_filename); + return 1; + } + + /* Create a portable timestamp. */ + currenttime = time(NULL); + { + /* avoid gcc complaints */ + const char *fmt = "%c UTC"; + strftime(utcTime, sizeof(utcTime), fmt, gmtime(¤ttime)); + } + fprintf(fp, "# $Id"); + fprintf(fp, "$\n"); + fprintf(fp, "# PcbXY Version 1.0\n"); + fprintf(fp, "# Date: %s\n", utcTime); + fprintf(fp, "# Author: %s\n", pcb_author()); + fprintf(fp, "# Title: %s - PCB X-Y\n", PCB_UNKNOWN(PCB->Name)); + fprintf(fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); + fprintf(fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->in_suffix); + fprintf(fp, "# --------------------------------------------\n"); + + /* + * For each element we calculate the centroid of the footprint. + * In addition, we need to extract some notion of rotation. + * While here generate the export_test list + */ + + 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; + found_pin1 = 0; + found_pin2 = 0; + + /* insert this component into the bill of materials list */ + export_test = export_test_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)), export_test); + + + /* + * 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++; + + if (PCB_NSTRCMP(pin->Number, "1") == 0) { + pin1x = (double) pin->X; + pin1y = (double) pin->Y; + pin1angle = 0.0; /* pins have no notion of angle */ + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pin->Number, "2") == 0) { + pin2x = (double) pin->X; + pin2y = (double) pin->Y; + found_pin2 = 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++; + + if (PCB_NSTRCMP(pad->Number, "1") == 0) { + pin1x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; + pin1y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; + /* + * 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. + */ + pin1angle = (180.0 / M_PI) * atan2(pad->Point1.Y - pad->Point2.Y, pad->Point2.X - pad->Point1.X); + found_pin1 = 1; + } + else if (PCB_NSTRCMP(pad->Number, "2") == 0) { + pin2x = (double) (pad->Point1.X + pad->Point2.X) / 2.0; + pin2y = (double) (pad->Point1.Y + pad->Point2.Y) / 2.0; + found_pin2 = 1; + } + + } + PCB_END_LOOP; + + if (pin_cnt > 0) { + x = sumx / (double) pin_cnt; + y = sumy / (double) pin_cnt; + + if (found_pin1) { + /* recenter pin #1 onto the axis which cross at the part + centroid */ + pin1x -= x; + pin1y -= y; + pin1y = -1.0 * pin1y; + + /* if only 1 pin, use pin 1's angle */ + if (pin_cnt == 1) + theta = pin1angle; + else { + /* if pin #1 is at (0,0) use pin #2 for rotation */ + if ((pin1x == 0.0) && (pin1y == 0.0)) { + if (found_pin2) + theta = xyToAngle(pin2x, pin2y); + else { + Message + ("Printexport_test(): unable to figure out angle of element\n" + " %s because pin #1 is at the centroid of the part.\n" + " and I could not find pin #2's location\n" + " Setting to %g degrees\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), theta); + } + } + else + theta = xyToAngle(pin1x, pin1y); + } + } + /* we did not find pin #1 */ + else { + theta = 0.0; + Message + ("Printexport_test(): unable to figure out angle because I could\n" + " not find pin #1 of element %s\n" " Setting to %g degrees\n", PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element)), theta); + } + + name = Cleanexport_testString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element))); + descr = Cleanexport_testString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element))); + value = Cleanexport_testString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_VALUE(element))); + + y = PCB->MaxHeight - y; + pcb_fprintf(fp, "%m+%s,\"%s\",\"%s\",%mS,%.2mS,%g,%s\n", + xy_unit->allow, name, descr, value, x, y, theta, PCB_FRONT(element) == 1 ? "top" : "bottom"); + free(name); + free(descr); + free(value); + } + } + PCB_END_LOOP; + + fclose(fp); + + /* Now print out a Bill of Materials file */ + + fp = fopen(export_test_filename, "w"); + if (!fp) { + gui->log("Cannot open file %s for writing\n", export_test_filename); + print_and_free(NULL, export_test); + return 1; + } + + fprintf(fp, "# $Id"); + fprintf(fp, "$\n"); + fprintf(fp, "# Pcbexport_test Version 1.0\n"); + fprintf(fp, "# Date: %s\n", utcTime); + fprintf(fp, "# Author: %s\n", pcb_author()); + fprintf(fp, "# Title: %s - PCB export_test\n", PCB_UNKNOWN(PCB->Name)); + fprintf(fp, "# Quantity, Description, Value, RefDes\n"); + fprintf(fp, "# --------------------------------------------\n"); + + print_and_free(fp, export_test); + + fclose(fp); + +#endif + 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 foo.pcb [export_test_options]\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.3/src_plugins/export_test/export_test.pup =================================================================== --- tags/1.2.3/src_plugins/export_test/export_test.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_test/export_test.pup (revision 8969) @@ -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.3/src_plugins/export_xy/Makefile =================================================================== --- tags/1.2.3/src_plugins/export_xy/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/export_xy/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_export_xy + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/export_xy/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/export_xy/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/export_xy/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/export_xy/export_xy.pup =================================================================== --- tags/1.2.3/src_plugins/export_xy/export_xy.pup (nonexistent) +++ tags/1.2.3/src_plugins/export_xy/export_xy.pup (revision 8969) @@ -0,0 +1,7 @@ +$class export +$short xy (centroid) pcb_exporter +$long Export XY centroid element data for pick & place. +$state works +default buildin +dep export_bom +autoload 1 Index: tags/1.2.3/src_plugins/export_xy/xy.c =================================================================== --- tags/1.2.3/src_plugins/export_xy/xy.c (nonexistent) +++ tags/1.2.3/src_plugins/export_xy/xy.c (revision 8969) @@ -0,0 +1,392 @@ +#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 "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 = "bom HID"; + +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 BOM 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 +}; + +#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; + + /* 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}; + +static int PrintXY(void) +{ + char utcTime[64]; + pcb_coord_t x, y; + double theta = 0.0; + double sumx, sumy; + double pin1x = 0.0, pin1y = 0.0; + int pin_cnt; + time_t currenttime; + FILE *fp; + char *name, *descr, *value, *fixed_rotation; + 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; + + + fp = fopen(xy_filename, "w"); + if (!fp) { + pcb_gui->log("Cannot open file %s for writing\n", xy_filename); + return 1; + } + + /* Create a portable timestamp. */ + currenttime = time(NULL); + { + /* avoid gcc complaints */ + const char *fmt = "%c UTC"; + strftime(utcTime, sizeof(utcTime), fmt, gmtime(¤ttime)); + } + fprintf(fp, "# $Id"); + fprintf(fp, "$\n"); + fprintf(fp, "# PcbXY Version 1.0\n"); + fprintf(fp, "# Date: %s\n", utcTime); + fprintf(fp, "# Author: %s\n", pcb_author()); + fprintf(fp, "# Title: %s - PCB X-Y\n", PCB_UNKNOWN(PCB->Name)); + fprintf(fp, "# RefDes, Description, Value, X, Y, rotation, top/bottom\n"); + fprintf(fp, "# X,Y in %s. rotation in degrees.\n", xy_unit->in_suffix); + fprintf(fp, "# --------------------------------------------\n"); + + /* + * 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; + + /* + * 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) { + x = element->MarkX; + y = element->MarkY; + } + else { + x = centroidx; + y = centroidy; + } + + fixed_rotation = pcb_attribute_get(&element->Attributes, "xy-fixed-rotation"); + if (fixed_rotation) { + /* The user specified a fixed rotation */ + theta = atof(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; + 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] - x; + pin1y = piny[rpindex] - y; + + /* flip x, to reverse rotation for elements on back */ + if (PCB_FRONT(element) != 1) + pin1x = -pin1x; + + /* if only 1 pin, use pin 1's angle */ + if (pin_cnt == 1) { + theta = pinangle[rpindex]; + found_any_not_at_centroid = 1; + } + else if ((pin1x != 0.0) || (pin1y != 0.0)) { + theta = xyToAngle(pin1x, pin1y, pin_cnt > 2); + found_any_not_at_centroid = 1; + } + } + } + + if (!found_any) { + pcb_message + (PCB_MSG_WARNING, "PrintBOM(): 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)), theta); + } + else if (!found_any_not_at_centroid) { + pcb_message + (PCB_MSG_WARNING, "PrintBOM(): 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)), theta); + } + } + } + + + name = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_REFDES(element))); + descr = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_DESCRIPTION(element))); + value = CleanBOMString((char *) PCB_UNKNOWN(PCB_ELEM_NAME_VALUE(element))); + + y = PCB->MaxHeight - y; + pcb_fprintf(fp, "%m+%s,\"%s\",\"%s\",%mS,%.2mS,%g,%s\n", + xy_unit->allow, name, descr, value, x, y, theta, PCB_FRONT(element) == 1 ? "top" : "bottom"); + free(name); + free(descr); + free(value); + } + PCB_END_LOOP; + + fclose(fp); + + return (0); +} + +static void xy_do_export(pcb_hid_attr_val_t * options) +{ + int i; + + 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]; + PrintXY(); +} + +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 foo.pcb [xy_options]\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) +{ +} + +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.3/src_plugins/fontmode/Makefile =================================================================== --- tags/1.2.3/src_plugins/fontmode/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/fontmode/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fontmode + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/fontmode/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/fontmode/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/fontmode/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/fontmode/fontmode.c =================================================================== --- tags/1.2.3/src_plugins/fontmode/fontmode.c (nonexistent) +++ tags/1.2.3/src_plugins/fontmode/fontmode.c (revision 8969) @@ -0,0 +1,383 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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(grp, lname); + assert(lid >= 0); + return &PCB->Data->Layer[lid]; +} + +static void add_poly(pcb_layer_t *layer, pcb_polygon_t *poly, pcb_coord_t ox, pcb_coord_t oy) +{ + int n; + pcb_point_t *pnt; + pcb_polygon_t *np; + + /* alloc */ + np = pcb_poly_new(layer, pcb_no_flags()); + pcb_poly_copy(np, poly); + + /* transform */ + for(n = 0, pnt = np->Points; n < np->PointN; n++,pnt++) { + pnt->X += ox; + pnt->Y += oy; + } + + /* add */ + pcb_add_polygon_on_layer(layer, np); + pcb_poly_init_clip(PCB->Data, layer, np); + DrawPolygon(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_polygon_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_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_polygon_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.3/src_plugins/fontmode/fontmode.pup =================================================================== --- tags/1.2.3/src_plugins/fontmode/fontmode.pup (nonexistent) +++ tags/1.2.3/src_plugins/fontmode/fontmode.pup (revision 8969) @@ -0,0 +1,6 @@ +$class feature +$short font editor +$long Font editing actions. +$state works +default buildin +autoload 1 Index: tags/1.2.3/src_plugins/fp_board/Makefile =================================================================== --- tags/1.2.3/src_plugins/fp_board/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/fp_board/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_board + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/fp_board/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/fp_board/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/fp_board/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/fp_board/fp_board.c =================================================================== --- tags/1.2.3/src_plugins/fp_board/fp_board.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_board/fp_board.c (revision 8969) @@ -0,0 +1,170 @@ + +#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" + +#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); + AddElementToBuffer(&op, element); + + f = fopen(tmp_name, "w"); + memset(&buff2, 0, sizeof(buff2)); + buff2.Data = op.buffer.dst; + pcb_write_buffer(f, &buff2, "pcb"); + fclose(f); + + pcb_data_free(op.buffer.dst); + free(op.buffer.dst); + + f = 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.fopen = fp_board_fopen; + fp_board.fclose = fp_board_fclose; + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_board); + return 0; +} Index: tags/1.2.3/src_plugins/fp_board/fp_board.pup =================================================================== --- tags/1.2.3/src_plugins/fp_board/fp_board.pup (nonexistent) +++ tags/1.2.3/src_plugins/fp_board/fp_board.pup (revision 8969) @@ -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.3/src_plugins/fp_fs/Makefile =================================================================== --- tags/1.2.3/src_plugins/fp_fs/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/fp_fs/Makefile (revision 8969) @@ -0,0 +1,5 @@ +all: + cd ../../src && $(MAKE) mod_fp_fs + +clean: + rm *.o *.so 2>/dev/null ; true Index: tags/1.2.3/src_plugins/fp_fs/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/fp_fs/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/fp_fs/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/fp_fs/fp_fs.c =================================================================== --- tags/1.2.3/src_plugins/fp_fs/fp_fs.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_fs/fp_fs.c (revision 8969) @@ -0,0 +1,530 @@ +/* + * 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 + * + */ + +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + +#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" + +/* 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 */ + if ((*suffix == '\0') || (pcb_strcasecmp(suffix, ".fp") == 0) || (pcb_strcasecmp(suffix, ".ele") == 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; +} + +/* 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 = 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 == '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[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 = conf_core.rc.library_shell; + + 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 = popen(cmd, "r"); + free(cmd); + } + else + f = 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) + 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.fopen = fp_fs_fopen; + fp_fs.fclose = fp_fs_fclose; + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_fs); + return 0; +} Index: tags/1.2.3/src_plugins/fp_fs/fp_fs.pup =================================================================== --- tags/1.2.3/src_plugins/fp_fs/fp_fs.pup (nonexistent) +++ tags/1.2.3/src_plugins/fp_fs/fp_fs.pup (revision 8969) @@ -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.3/src_plugins/fp_wget/Makefile =================================================================== --- tags/1.2.3/src_plugins/fp_wget/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/Makefile (revision 8969) @@ -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.3/src_plugins/fp_wget/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/fp_wget/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/fp_wget/edakrill.c =================================================================== --- tags/1.2.3/src_plugins/fp_wget/edakrill.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/edakrill.c (revision 8969) @@ -0,0 +1,264 @@ +#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" + +#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 = 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"); + 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.fopen = fp_edakrill_fopen; + fp_edakrill.fclose = fp_edakrill_fclose; + + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_edakrill); +} Index: tags/1.2.3/src_plugins/fp_wget/edakrill.h =================================================================== --- tags/1.2.3/src_plugins/fp_wget/edakrill.h (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/edakrill.h (revision 8969) @@ -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.3/src_plugins/fp_wget/fp_wget.c =================================================================== --- tags/1.2.3/src_plugins/fp_wget/fp_wget.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/fp_wget.c (revision 8969) @@ -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.3/src_plugins/fp_wget/fp_wget.pup =================================================================== --- tags/1.2.3/src_plugins/fp_wget/fp_wget.pup (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/fp_wget.pup (revision 8969) @@ -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.3/src_plugins/fp_wget/fp_wget_conf.h =================================================================== --- tags/1.2.3/src_plugins/fp_wget/fp_wget_conf.h (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/fp_wget_conf.h (revision 8969) @@ -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.3/src_plugins/fp_wget/gedasymbols.c =================================================================== --- tags/1.2.3/src_plugins/fp_wget/gedasymbols.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/gedasymbols.c (revision 8969) @@ -0,0 +1,172 @@ +#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" + +#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 = 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"); + 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.fopen = fp_gedasymbols_fopen; + fp_gedasymbols.fclose = fp_gedasymbols_fclose; + + PCB_HOOK_REGISTER(pcb_plug_fp_t, pcb_plug_fp_chain, &fp_gedasymbols); +} Index: tags/1.2.3/src_plugins/fp_wget/gedasymbols.h =================================================================== --- tags/1.2.3/src_plugins/fp_wget/gedasymbols.h (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/gedasymbols.h (revision 8969) @@ -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.3/src_plugins/fp_wget/tester.c =================================================================== --- tags/1.2.3/src_plugins/fp_wget/tester.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/tester.c (revision 8969) @@ -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.3/src_plugins/fp_wget/wget_common.c =================================================================== --- tags/1.2.3/src_plugins/fp_wget/wget_common.c (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/wget_common.c (revision 8969) @@ -0,0 +1,158 @@ +/* for popen() */ +#define _DEFAULT_SOURCE +#define _BSD_SOURCE + + +#include +#include +#include +#include "config.h" +#include "wget_common.h" +#include "compat_misc.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 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 = 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); + system(cmd); + } + if (f != NULL) { + sprintf(cmd, "%s/%s", cache_path, cdir); + *f = 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: 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 = 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.3/src_plugins/fp_wget/wget_common.h =================================================================== --- tags/1.2.3/src_plugins/fp_wget/wget_common.h (nonexistent) +++ tags/1.2.3/src_plugins/fp_wget/wget_common.h (revision 8969) @@ -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.3/src_plugins/gpmi/Makefile =================================================================== --- tags/1.2.3/src_plugins/gpmi/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_pcb_gpmi + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/gpmi/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/gpmi/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/gpmi/gpmi.pup =================================================================== --- tags/1.2.3/src_plugins/gpmi/gpmi.pup (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/gpmi.pup (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/Makefile =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/Makefile (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/Makefile.config.in =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/Makefile.config.in (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/Makefile.config.in (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/Makefile (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.am (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/Makefile.dep (revision 8969) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/actions.h (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi/package.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/actions/gpmi.conf (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.am (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/Makefile.dep (revision 8969) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/coordgeo.h (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi/package.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/gpmi.conf (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/coordgeo/test.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.am (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/Makefile.dep (revision 8969) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.c (revision 8969) @@ -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); +} Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/dialogs.h (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/dialogs/gpmi.conf (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.am (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/Makefile.dep (revision 8969) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi/package.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/gpmi.conf (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.c (revision 8969) @@ -0,0 +1,308 @@ +#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->hid->use_mask = gpmi_hid_use_mask; + + 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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid.h (revision 8969) @@ -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_polygon_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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.c (revision 8969) @@ -0,0 +1,177 @@ +#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_pcb_polygon(pcb_hid_gc_t gc, pcb_polygon_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_use_mask(pcb_mask_op_t use_it) +{ + gpmi_hid_t *h = hid_gpmi_data_get(pcb_exporter); + gpmi_event(h->module, HIDE_use_mask, h, use_it); +} + +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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_callbacks.h (revision 8969) @@ -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_pcb_polygon(pcb_hid_gc_t gc, pcb_polygon_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); +void gpmi_hid_use_mask(pcb_mask_op_t use_it); Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/hid/hid_events.h (revision 8969) @@ -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 rectangle */ +gpmi_define_event(HIDE_fill_rect)(void *hid, void *gc, int x1, int y1, int x2, int y2); + +/* PCB callback events for drawing: TODO */ +gpmi_define_event(HIDE_use_mask)(void *hid, int use_it); + +/* 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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.am (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/Makefile.dep (revision 8969) @@ -0,0 +1 @@ +#Please run make depend! Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/coord.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/create.c (revision 8969) @@ -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(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(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(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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/debug_draw.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/draw.c (revision 8969) @@ -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 draw_line(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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/gpmi.conf (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layers.c (revision 8969) @@ -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].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].On; + case LFLD_NODRC: return PCB->Data->Layer[layer].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(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(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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/layout.h (revision 8969) @@ -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_polygon_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 draw_line(dctx_t *ctx, int x1_, int y1_, int x2_, int y2_); + +/* +void draw_arc(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_polygon_t *poly, const pcb_box_t *clip_box); +void thindraw_pcb_polygon(dctx_t *ctx, pcb_polygon_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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/object.c (revision 8969) @@ -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(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_POLYGON, 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(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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/page.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_pkg/layout/search.c (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.c (revision 8969) @@ -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() +{ + pcb_hid_action_t act; + + act.name = "gpmi_scripts"; + act.need_coord_msg = NULL; + act.description = "Manage gpmi scripts"; + act.syntax = "TODO"; + act.trigger_cb = action_gpmi_scripts; + pcb_hid_register_action(&act, gpmi_cookie, 0); + + act.name = "rehash"; + act.need_coord_msg = NULL; + act.description = "Reload all gpmi scripts"; + act.syntax = "TODO"; + act.trigger_cb = action_gpmi_rehash; + pcb_hid_register_action(&act, 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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/gpmi_plugin.h (revision 8969) @@ -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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.c (revision 8969) @@ -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"); + + /* 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")) + 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"); + 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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/manage_scripts.h (revision 8969) @@ -0,0 +1 @@ +void gpmi_hid_manage_scripts(void); Index: tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.c (revision 8969) @@ -0,0 +1,386 @@ +#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" + +#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 = 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 = 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 = 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 (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 = 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.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h =================================================================== --- tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h (nonexistent) +++ tags/1.2.3/src_plugins/gpmi/pcb-gpmi/gpmi_plugin/scripts.h (revision 8969) @@ -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.3/src_plugins/hid_batch/Makefile =================================================================== --- tags/1.2.3/src_plugins/hid_batch/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/hid_batch/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_batch + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/hid_batch/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/hid_batch/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/hid_batch/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/hid_batch/batch.c =================================================================== --- tags/1.2.3/src_plugins/hid_batch/batch.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_batch/batch.c (revision 8969) @@ -0,0 +1,397 @@ +#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(); + return; + } + pcb_hid_parse_command(line); + } + 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_use_mask(pcb_mask_op_t use_it) +{ +} + +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_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, void (*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_) +{ + 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) +{ +} + +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.use_mask = batch_use_mask; + 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_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.3/src_plugins/hid_batch/hid_batch.pup =================================================================== --- tags/1.2.3/src_plugins/hid_batch/hid_batch.pup (nonexistent) +++ tags/1.2.3/src_plugins/hid_batch/hid_batch.pup (revision 8969) @@ -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.3/src_plugins/hid_gtk2_gdk/Makefile =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gdk + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/hid_gtk2_gdk/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/gtkhid-gdk.c (revision 8969) @@ -0,0 +1,1440 @@ +#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 + +static int cur_mask = -1; +static int mask_seq = 0; + +typedef struct render_priv_s { + GdkGC *bg_gc; + GdkColor bg_color; + GdkGC *offlimits_gc; + GdkColor offlimits_color; + GdkGC *mask_gc; + GdkGC *u_gc; + GdkGC *grid_gc; + GdkColor grid_color; + GdkPixmap *pixmap, *mask; + GdkDrawable *drawable; /* Current drawable for drawing routines */ + pcb_bool clip; + GdkRectangle clip_rect; + int attached_invalidate_depth; + int mark_invalidate_depth; +} render_priv_t; + + +typedef struct hid_gc_s { + pcb_hid_t *me_pointer; + GdkGC *gc; + + gchar *colorname; + pcb_coord_t width; + gint cap, join; + gchar xor_mask; + gint mask_seq; +} hid_gc_s; + +static void draw_lead_user(render_priv_t *priv_); + +static const gchar *get_color_name(GdkColor * 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, GdkColor * 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].On) + 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].On; + + /* 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->gc) + g_object_unref(gc->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) + 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->drawable, 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->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_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->drawable); + 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->drawable, priv->bg_gc, src_x, src_y, dst_x, dst_y, w - src_x, h - src_y, GDK_RGB_DITHER_NORMAL, 0, 0); +} + +#define WHICH_GC(gc) (((cur_mask == HID_MASK_CLEAR) || (cur_mask == HID_MASK_SET)) ? priv->mask_gc : (gc)->gc) + +static void ghid_mask_setup(render_priv_t *priv) +{ + if (!priv->mask) + priv->mask = gdk_pixmap_new(0, gport->view.canvas_width, gport->view.canvas_height, 1); + priv->drawable = priv->mask; + if (!priv->mask_gc) { + priv->mask_gc = gdk_gc_new(priv->drawable); + gdk_gc_set_clip_origin(priv->mask_gc, 0, 0); + set_clip(priv, priv->mask_gc); + } +} + +static void ghid_gdk_use_mask(pcb_mask_op_t use_it) +{ + static int mask_seq_id = 0; + GdkColor color; + render_priv_t *priv = gport->render_priv; + + if (!priv->pixmap) + return; + if (use_it == cur_mask) + return; + switch (use_it) { + case HID_MASK_OFF: + priv->drawable = priv->pixmap; + mask_seq = 0; + break; + + case HID_MASK_BEFORE: + /* The HID asks not to receive this mask type, so warn if we get it */ + g_return_if_reached(); + + case HID_MASK_INIT: + ghid_mask_setup(priv); + mask_seq = 0; + + /* clear the mask */ + color.pixel = 0; + gdk_gc_set_foreground(priv->mask_gc, &color); + gdk_draw_rectangle(priv->drawable, priv->mask_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + break; + + case HID_MASK_CLEAR: + color.pixel = 0; + gdk_gc_set_foreground(priv->mask_gc, &color); + break; + + case HID_MASK_SET: + color.pixel = 1; + gdk_gc_set_foreground(priv->mask_gc, &color); + break; + + case HID_MASK_AFTER: + mask_seq_id++; + if (!mask_seq_id) + mask_seq_id = 1; + mask_seq = mask_seq_id; + + priv->drawable = priv->pixmap; + break; + + } + cur_mask = use_it; +} + + +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) +{ + 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->gc) + return; + if (colormap == NULL) + colormap = gtk_widget_get_colormap(gport->top_window); + + if (strcmp(name, "erase") == 0) { + gdk_gc_set_foreground(gc->gc, &priv->bg_color); + } + else if (strcmp(name, "drill") == 0) { + gdk_gc_set_foreground(gc->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->gc, &cc->xor_color); + } + else { + gdk_gc_set_foreground(gc->gc, &cc->color); + } + } +} + +static void ghid_gdk_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + render_priv_t *priv = gport->render_priv; + + 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->gc) + gdk_gc_set_line_attributes(WHICH_GC(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) +{ + render_priv_t *priv = gport->render_priv; + + gc->width = 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_gdk_set_draw_xor(pcb_hid_gc_t gc, int xor_mask) +{ + gc->xor_mask = xor_mask; + if (!gc->gc) + return; + gdk_gc_set_function(gc->gc, xor_mask ? GDK_XOR : GDK_COPY); + ghid_gdk_set_color(gc, gc->colorname); +} + +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); + + if (gc->me_pointer != >k2_gdk_hid) { + fprintf(stderr, "Fatal: GC from another HID passed to GTK HID\n"); + abort(); + } + + if (!priv->pixmap) + return 0; + if (!gc->gc) { + gc->gc = gdk_gc_new(window); + 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->gc, 0, 0); + } + if (gc->mask_seq != mask_seq) { + if (mask_seq) + gdk_gc_set_clip_mask(gc->gc, priv->mask); + else + set_clip(priv, gc->gc); + gc->mask_seq = mask_seq; + } + priv->u_gc = WHICH_GC(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; + + 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->drawable, priv->u_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; + + 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->drawable, priv->u_gc, 0, + pcb_round(Vxd(cx) - Vzd(xradius) + 0.5), pcb_round(Vyd(cy) - Vzd(yradius) + 0.5), + pcb_round(vrx2), pcb_round(vry2), + (start_angle + 180) * 64, delta_angle * 64); +} + +static void 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; + + 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->drawable, priv->u_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; + + 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->drawable, priv->u_gc, TRUE, Vx(cx) - vr, Vy(cy) - vr, vr * 2, vr * 2, 0, 360 * 64); +} + +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); + + 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->drawable, priv->u_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; + + 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->drawable, priv->u_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->pixmap) + 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.elem = 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->drawable, priv->offlimits_gc, 1, 0, 0, eleft, gport->view.canvas_height); + else + eleft = 0; + if (eright < gport->view.canvas_width) + gdk_draw_rectangle(priv->drawable, 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->drawable, priv->offlimits_gc, 1, eleft, 0, eright - eleft + 1, etop); + else + etop = 0; + if (ebottom < gport->view.canvas_height) + gdk_draw_rectangle(priv->drawable, priv->offlimits_gc, 1, eleft, ebottom, eright - eleft + 1, gport->view.canvas_height - ebottom); + else + ebottom = gport->view.canvas_height; + + gdk_draw_rectangle(priv->drawable, 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 = 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->pixmap) + gdk_pixmap_unref(priv->pixmap); + + priv->pixmap = gdk_pixmap_new(gtk_widget_get_window(gport->drawing_area), + gport->view.canvas_width, gport->view.canvas_height, -1); + priv->drawable = priv->pixmap; + gport->drawing_allowed = pcb_true; + + if (!done_once) { + priv->bg_gc = gdk_gc_new(priv->drawable); + 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->drawable); + 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->mask) { + gdk_pixmap_unref(priv->mask); + priv->mask = 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->pixmap == NULL) + return; + + gdk_draw_drawable(window, priv->bg_gc, priv->pixmap, 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, GdkEventExpose * 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->pixmap, + 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, GdkEventExpose * 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->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; + + priv->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; + + /* 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->drawable = save_drawable; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static void *ghid_gdk_render_pixmap(int cx, int cy, double zoom, int width, int height, int depth) +{ + GdkPixmap *pixmap; + GdkDrawable *save_drawable; + pcb_gtk_view_t save_view; + int save_width, save_height; + pcb_hid_expose_ctx_t ectx; + render_priv_t *priv = gport->render_priv; + + save_drawable = priv->drawable; + save_view = gport->view; + save_width = gport->view.canvas_width; + save_height = gport->view.canvas_height; + + pixmap = gdk_pixmap_new(NULL, width, height, depth); + + /* Setup drawable and zoom factor for drawing routines + */ + + priv->drawable = pixmap; + gport->view.coord_per_px = zoom; + gport->view.canvas_width = width; + gport->view.canvas_height = height; + gport->view.width = width * gport->view.coord_per_px; + gport->view.height = height * gport->view.coord_per_px; + gport->view.x0 = conf_core.editor.view.flip_x ? PCB->MaxWidth - cx : cx; + gport->view.x0 -= gport->view.height / 2; + gport->view.y0 = conf_core.editor.view.flip_y ? PCB->MaxHeight - cy : cy; + gport->view.y0 -= gport->view.width / 2; + + /* clear background */ + gdk_draw_rectangle(pixmap, priv->bg_gc, TRUE, 0, 0, width, height); + + /* call the drawing routine */ + ectx.view.X1 = MIN(Px(0), Px(gport->view.canvas_width + 1)); + ectx.view.Y1 = MIN(Py(0), Py(gport->view.canvas_height + 1)); + ectx.view.X2 = MAX(Px(0), Px(gport->view.canvas_width + 1)); + ectx.view.Y2 = MAX(Py(0), Py(gport->view.canvas_height + 1)); + + ectx.view.X1 = MAX(0, MIN(PCB->MaxWidth, ectx.view.X1)); + ectx.view.X2 = MAX(0, MIN(PCB->MaxWidth, ectx.view.X2)); + ectx.view.Y1 = MAX(0, MIN(PCB->MaxHeight, ectx.view.Y1)); + ectx.view.Y2 = MAX(0, MIN(PCB->MaxHeight, ectx.view.Y2)); + + ectx.force = 0; + ectx.content.elem = NULL; + + pcb_hid_expose_all(>k2_gdk_hid, &ectx); + + priv->drawable = save_drawable; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return pixmap; +} + +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->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_gdk_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + if (common != NULL) { + common->render_pixmap = ghid_gdk_render_pixmap; + 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->use_mask = ghid_gdk_use_mask; + 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_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.3/src_plugins/hid_gtk2_gdk/gtkhid-main.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/gtkhid-main.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/gtkhid-main.c (revision 8969) @@ -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.3/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/hid_gtk2_gdk.pup (revision 8969) @@ -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.3/src_plugins/hid_gtk2_gdk/pcb.rc =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gdk/pcb.rc (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gdk/pcb.rc (revision 8969) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/1.2.3/src_plugins/hid_gtk2_gl/Makefile =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk2_gl + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/hid_gtk2_gl/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/Plug.tmpasm (revision 8969) @@ -0,0 +1,20 @@ +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 +@] + +switch /local/pcb/hid_gtk2_gl/controls + case {disable} end; + default + put /local/pcb/mod/CFLAGS /target/libs/gui/gtk2gl/cflags + put /local/pcb/mod/LDFLAGS /target/libs/gui/gtk2gl/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.3/src_plugins/hid_gtk2_gl/gtkhid-gl.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/gtkhid-gl.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/gtkhid-gl.c (revision 8969) @@ -0,0 +1,1316 @@ +#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" + + +/* 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 +#ifdef HAVE_OPENGL_GL_H +#include +#else +#include +#endif + +#include +#include "hidgl.h" +#include "hid_draw_helpers.h" + +#include "../src_plugins/lib_gtk_config/hid_gtk_conf.h" + +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 int cur_mask = -1; + +typedef struct render_priv_s { + GdkGLConfig *glconfig; + GdkColor bg_color, offlimits_color, 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); + +static const gchar *get_color_name(GdkColor * 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, GdkColor * 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; +} + + +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(&buffer); + + 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(&buffer); + + 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; +} + + +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].On) + break; + } + idx = PCB->LayerGroups.grp[group].lid[idx]; + } + + 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) { + priv->trans_lines = pcb_true; + return PCB->Data->Layer[idx].On; + } + + /* virtual layers */ + { + switch (flags & PCB_LYT_ANYTHING) { + case PCB_LYT_INVIS: + return PCB->InvisibleObjectsOn; + 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) +{ + end_subcomposite(); +} + +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) +{ +#warning draw_grid_local stubbed out for now +} + +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) + 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.); + +#warning this does not draw the local grid and ignores other new grid options + 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); +} + +void ghid_gl_use_mask(pcb_mask_op_t use_it) +{ + static int stencil_bit = 0; + + if (use_it == cur_mask) + return; + + /* Flush out any existing geoemtry to be rendered */ + hidgl_flush_triangles(&buffer); + + switch (use_it) { + case HID_MASK_BEFORE: + /* The HID asks not to receive this mask type, so warn if we get it */ + g_return_if_reached(); + + case HID_MASK_INIT: + glColorMask(0, 0, 0, 0); /* Disable writting in color buffer */ + glEnable(GL_STENCIL_TEST); /* Enable Stencil test */ + stencil_bit = hidgl_assign_clear_stencil_bit(); /* Get a new (clean) bitplane to stencil with */ + break; + + case HID_MASK_CLEAR: + /* Write '0' to the stencil buffer where the solder-mask should not be drawn ("transparent", "cutout"). */ + glStencilFunc(GL_ALWAYS, stencil_bit, stencil_bit); /* Always pass stencil test, write stencil_bit */ + glStencilMask(stencil_bit); /* Only write to our subcompositing stencil bitplane */ + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); /* Stencil pass => replace stencil value (with 1) */ + break; + + case HID_MASK_SET: + /* Write '1' to the stencil buffer where the solder-mask should be drawn ("red", "solid"). */ + glStencilFunc(GL_ALWAYS, stencil_bit, stencil_bit); /* Always pass stencil test, write stencil_bit */ + glStencilMask(stencil_bit); /* Only write to our subcompositing stencil bitplane */ + glStencilOp(GL_KEEP, GL_KEEP, GL_ZERO); /* Stencil pass => replace stencil value (with 1) */ + break; + + case HID_MASK_AFTER: + /* Drawing operations as masked to areas where the stencil buffer is '0' */ + glColorMask(1, 1, 1, 1); /* Enable drawing of r, g, b & a */ + glStencilFunc(GL_GEQUAL, 0, stencil_bit); /* Draw only where our bit of the stencil buffer is clear */ + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); /* Stencil buffer read only */ + break; + + case HID_MASK_OFF: + /* Disable stenciling */ + hidgl_return_stencil_bit(stencil_bit); /* Relinquish any bitplane we previously used */ + glDisable(GL_STENCIL_TEST); /* Disable Stencil test */ + break; + } + cur_mask = use_it; +} + + + /* Config helper functions for when the user changes color preferences. + | set_special colors used in the gtkhid. + */ +static void set_special_grid_color(void) +{ + render_priv_t *priv = gport->render_priv; + + priv->grid_color.red ^= priv->bg_color.red; + priv->grid_color.green ^= priv->bg_color.green; + priv->grid_color.blue ^= priv->bg_color.blue; +} + +void ghid_gl_set_special_colors(conf_native_t *cfg) +{ + render_priv_t *priv = gport->render_priv; + + if (((CFT_COLOR *)cfg->val.color == &conf_core.appearance.color.background)) { + if (map_color_string(cfg->val.color[0], &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; + + hidgl_flush_triangles(&buffer); + glColor4d(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; +} + + +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); + + hidgl_draw_rect(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_pcb_polygon(pcb_hid_gc_t gc, pcb_polygon_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_polygon_t * poly, const pcb_box_t * clip_box) +{ + pcb_dhlp_thindraw_pcb_polygon(gc, poly, clip_box); + 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) +{ +} + +#define Z_NEAR 3.0 +gboolean ghid_gl_drawing_area_expose_cb(GtkWidget * widget, GdkEventExpose * 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 (hidgl_stencil_bits() == 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); + hidgl_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(); + + hidgl_init_triangle_array(&buffer); + ghid_gl_invalidate_current_gc(); + pcb_hid_expose_all(>k2_gl_hid, &ctx); + hidgl_flush_triangles(&buffer); + + ghid_gl_draw_grid(&ctx.view); + + ghid_gl_invalidate_current_gc(); + + pcb_draw_attached(); + pcb_draw_mark(); + hidgl_flush_triangles(&buffer); + + ghid_gl_show_crosshair(TRUE); + + hidgl_flush_triangles(&buffer); + + 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, GdkEventExpose * 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); + + hidgl_reset_stencil_usage(); + glDisable(GL_STENCIL_TEST); + glStencilMask(0); + glStencilFunc(GL_ALWAYS, 0, 0); + + /* call the drawing routine */ + hidgl_init_triangle_array(&buffer); + 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); + + hidgl_flush_triangles(&buffer); + 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; +} + +/*GdkPixmap*/void *ghid_gl_render_pixmap(int cx, int cy, double zoom, int width, int height, int depth) +{ + GdkGLConfig *glconfig; + GdkPixmap *pixmap; + GdkGLPixmap *glpixmap; + GdkGLContext *glcontext; + GdkGLDrawable *gldrawable; + render_priv_t *priv = gport->render_priv; + pcb_gtk_view_t save_view; + int save_width, save_height; + pcb_hid_expose_ctx_t ctx; + + save_view = gport->view; + save_width = gport->view.canvas_width; + save_height = gport->view.canvas_height; + + /* Setup rendering context for drawing routines + */ + + glconfig = gdk_gl_config_new_by_mode(GDK_GL_MODE_RGB | GDK_GL_MODE_STENCIL | GDK_GL_MODE_SINGLE); + + pixmap = gdk_pixmap_new(NULL, width, height, depth); + glpixmap = gdk_pixmap_set_gl_capability(pixmap, glconfig, NULL); + gldrawable = GDK_GL_DRAWABLE(glpixmap); + glcontext = gdk_gl_context_new(gldrawable, NULL, TRUE, GDK_GL_RGBA_TYPE); + + /* Setup zoom factor for drawing routines */ + + gport->view.coord_per_px = zoom; + gport->view.canvas_width = width; + gport->view.canvas_height = height; + gport->view.width = width * gport->view.coord_per_px; + gport->view.height = height * gport->view.coord_per_px; + gport->view.x0 = conf_core.editor.view.flip_x ? PCB->MaxWidth - cx : cx; + gport->view.x0 -= gport->view.height / 2; + gport->view.y0 = conf_core.editor.view.flip_y ? PCB->MaxHeight - cy : cy; + gport->view.y0 -= gport->view.width / 2; + + /* make GL-context "current" */ + if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext)) { + return NULL; + } + gport->render_priv->in_context = pcb_true; + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glViewport(0, 0, width, height); + + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, width, height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, 0, 100); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0f, 0.0f, -Z_NEAR); + + 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); + hidgl_reset_stencil_usage(); + + /* call the drawing routine */ + hidgl_init_triangle_array(&buffer); + 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); + + ctx.view.X1 = MIN(Px(0), Px(gport->view.canvas_width + 1)); + ctx.view.Y1 = MIN(Py(0), Py(gport->view.canvas_height + 1)); + ctx.view.X2 = MAX(Px(0), Px(gport->view.canvas_width + 1)); + ctx.view.Y2 = MAX(Py(0), Py(gport->view.canvas_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)); + + pcb_hid_expose_all(>k2_gl_hid, &ctx); + hidgl_flush_triangles(&buffer); + glPopMatrix(); + + glFlush(); + + /* end drawing to current GL-context */ + gport->render_priv->in_context = pcb_false; + gdk_gl_drawable_gl_end(gldrawable); + + gdk_pixmap_unset_gl_capability(pixmap); + + g_object_unref(glconfig); + g_object_unref(glcontext); + + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return pixmap; +} + +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); + + hidgl_flush_triangles(&buffer); + + if (gdk_gl_drawable_is_double_buffered(pGlDrawable)) + gdk_gl_drawable_swap_buffers(pGlDrawable); + else + glFlush(); +} + +void ghid_gl_finish_debug_draw(void) +{ + hidgl_flush_triangles(&buffer); + 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); + } + + hidgl_flush_triangles(&buffer); + glPopAttrib(); +} + +void ghid_gl_install(pcb_gtk_common_t *common, pcb_hid_t *hid) +{ + if (common != NULL) { + common->render_pixmap = ghid_gl_render_pixmap; + 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->use_mask = ghid_gl_use_mask; + 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_rect = ghid_gl_fill_rect; + + 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; + } +} + Index: tags/1.2.3/src_plugins/hid_gtk2_gl/gtkhid-main.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/gtkhid-main.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/gtkhid-main.c (revision 8969) @@ -0,0 +1,97 @@ +#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_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); +} + +#include "layer.h" +#include "event.h" +#include "error.h" +#include "data.h" +static void warn_composite(void *user_data, int argc, pcb_event_arg_t argv[]) +{ + int lid; + + if (pcb_gui != >k2_gl_hid) + return; + + for(lid = 0; lid < pcb_max_layer; lid++) { + if (pcb_layer_flags(PCB, lid) & (PCB_LYT_MASK | PCB_LYT_PASTE)) + goto warn; + if (PCB->Data->Layer[lid].comb & PCB_LYC_SUB) + goto warn; + } + return; + + warn:; + pcb_message(PCB_MSG_ERROR, + "\n" + "! Compositing layers (editing mask or paste) is NOT SUPPORTED by\n" + "! the opengl renderer at the moment. The rendering on screen will\n" + "! be broken. Please save, exit and run pcb-rnd with --gui gtk2_gdk\n" + "\n"); +} + +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); +} + +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); + + pcb_event_bind(PCB_EVENT_LAYERS_CHANGED, warn_composite, NULL, ghid_gl_cookie); + + return 0; +} Index: tags/1.2.3/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/hid_gtk2_gl.pup (revision 8969) @@ -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.3/src_plugins/hid_gtk2_gl/hidgl.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/hidgl.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/hidgl.c (revision 8969) @@ -0,0 +1,735 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, 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" + +/* 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 +#ifdef HAVE_OPENGL_GL_H +#include +#else +#include +#endif + +#ifdef HAVE_OPENGL_GLU_H +#include +#else +#include +#endif + +#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" + + + +triangle_buffer buffer; +float global_depth = 0; + +void hidgl_init_triangle_array(triangle_buffer * buffer) +{ + buffer->triangle_count = 0; + buffer->coord_comp_count = 0; +} + +void hidgl_flush_triangles(triangle_buffer * buffer) +{ + if (buffer->triangle_count == 0) + return; + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, buffer->triangle_array); + glDrawArrays(GL_TRIANGLES, 0, buffer->triangle_count * 3); + glDisableClientState(GL_VERTEX_ARRAY); + + buffer->triangle_count = 0; + buffer->coord_comp_count = 0; +} + +void hidgl_ensure_triangle_space(triangle_buffer * buffer, int count) +{ + if (count > TRIANGLE_ARRAY_SIZE) { + fprintf(stderr, "Not enough space in vertex buffer\n"); + fprintf(stderr, "Requested %i triangles, %i available\n", count, TRIANGLE_ARRAY_SIZE); + exit(1); + } + if (count > TRIANGLE_ARRAY_SIZE - buffer->triangle_count) + hidgl_flush_triangles(buffer); +} + +void hidgl_set_depth(float depth) +{ + global_depth = depth; +} + +void hidgl_draw_grid(pcb_box_t * drawn_area) +{ + static GLfloat *points = 0; + static int npoints = 0; + pcb_coord_t x1, y1, x2, y2, n, i; + double x, y; + + if (!conf_core.editor.draw_grid) + return; + + 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; + if (n > npoints) { + npoints = n + 10; + points = realloc(points, npoints * 3 * sizeof(GLfloat)); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, points); + + n = 0; + for (x = x1; x <= x2; x += PCB->Grid) { + points[3 * n + 0] = x; + points[3 * n + 2] = global_depth; + n++; + } + for (y = y1; y <= y2; y += PCB->Grid) { + for (i = 0; i < n; i++) + points[3 * 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; + + hidgl_ensure_triangle_space(&buffer, 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; + hidgl_add_triangle(&buffer, 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; + int hairline = 0; + + if (width == 0.0) + hairline = 1; + + 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 = -width / 2.; + wdy = 0; + 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; + } + + hidgl_ensure_triangle_space(&buffer, 2); + hidgl_add_triangle(&buffer, x1 - wdx, y1 - wdy, x2 - wdx, y2 - wdy, x2 + wdx, y2 + wdy); + hidgl_add_triangle(&buffer, x1 - wdx, y1 - wdy, x2 + wdx, y2 + wdy, x1 + wdx, y1 + wdy); + + /* Don't bother capping hairlines */ + if (circular_caps && !hairline) { + 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; + + 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; + + hidgl_ensure_triangle_space(&buffer, 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; + hidgl_add_triangle(&buffer, last_inner_x, last_inner_y, last_outer_x, last_outer_y, outer_x, outer_y); + hidgl_add_triangle(&buffer, 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_draw_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + glBegin(GL_LINE_LOOP); + glVertex3f(x1, y1, global_depth); + glVertex3f(x1, y2, global_depth); + glVertex3f(x2, y2, global_depth); + glVertex3f(x2, y1, global_depth); + glEnd(); +} + + +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; + + 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; + + hidgl_ensure_triangle_space(&buffer, 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; + hidgl_add_triangle(&buffer, 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 { + hidgl_ensure_triangle_space(&buffer, 1); + hidgl_add_triangle(&buffer, + 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) { + hidgl_ensure_triangle_space(&buffer, 1); + hidgl_add_triangle(&buffer, + 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"); +} + +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); +} + +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; +} + +static GLint stencil_bits; +static int dirty_bits = 0; +static int assigned_bits = 0; + +/* FIXME: JUST DRAWS THE FIRST PIECE.. TODO: SUPPORT FOR FULLPOLY POLYGONS */ +void hidgl_fill_pcb_polygon(pcb_polygon_t * poly, const pcb_box_t * clip_box, double scale) +{ + int vertex_count = 0; + pcb_pline_t *contour; + struct do_hole_info info; + int stencil_bit; + + info.scale = scale; + global_scale = scale; + + if (poly->Clipped == NULL) { + fprintf(stderr, "hidgl_fill_pcb_polygon: poly->Clipped == NULL\n"); + return; + } + + stencil_bit = hidgl_assign_clear_stencil_bit(); + if (!stencil_bit) { + printf("hidgl_fill_pcb_polygon: No free stencil bits, aborting polygon\n"); + return; + } + + /* Flush out any existing geoemtry to be rendered */ + hidgl_flush_triangles(&buffer); + + /* Walk the polygon structure, counting vertices */ + /* This gives an upper bound on the amount of storage required */ + for (contour = poly->Clipped->contours; contour != NULL; contour = contour->next) + vertex_count = MAX(vertex_count, contour->Count); + + info.vertices = malloc(sizeof(GLdouble) * vertex_count * 3); + 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); + + glPushAttrib(GL_STENCIL_BUFFER_BIT); /* Save the write mask etc.. for final restore */ + glEnable(GL_STENCIL_TEST); + glPushAttrib(GL_STENCIL_BUFFER_BIT | /* Resave the stencil write-mask etc.., and */ + GL_COLOR_BUFFER_BIT); /* the colour buffer write mask etc.. for part way restore */ + glStencilMask(stencil_bit); /* Only write to our stencil bit */ + glStencilFunc(GL_ALWAYS, stencil_bit, stencil_bit); /* Always pass stencil test, ref value is our bit */ + glColorMask(0, 0, 0, 0); /* Disable writting in color buffer */ + + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); /* Stencil pass => replace stencil value */ + + /* Drawing operations now set our reference bit in the stencil buffer */ + + pcb_r_search(poly->Clipped->contour_tree, clip_box, NULL, do_hole, &info, NULL); + hidgl_flush_triangles(&buffer); + + glPopAttrib(); /* Restore the colour and stencil buffer write-mask etc.. */ + + glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); /* This allows us to toggle the bit on any subcompositing bitplane */ + /* If the stencil test has passed, we know that bit is 0, so we're */ + /* effectively just setting it to 1. */ + + glStencilFunc(GL_GEQUAL, 0, assigned_bits); /* Pass stencil test if all assigned bits clear, */ + /* reference is all assigned bits so we set */ + /* any bits permitted by the stencil writemask */ + + /* Drawing operations as masked to areas where the stencil buffer is '0' */ + + /* Draw the polygon outer */ + tesselate_contour(info.tobj, poly->Clipped->contours, info.vertices, scale); + hidgl_flush_triangles(&buffer); + + /* Unassign our stencil buffer bit */ + hidgl_return_stencil_bit(stencil_bit); + + glPopAttrib(); /* Restore the stencil buffer write-mask etc.. */ + + gluDeleteTess(info.tobj); + myFreeCombined(); + free(info.vertices); +} + +void hidgl_fill_rect(pcb_coord_t x1, pcb_coord_t y1, pcb_coord_t x2, pcb_coord_t y2) +{ + hidgl_ensure_triangle_space(&buffer, 2); + hidgl_add_triangle(&buffer, x1, y1, x1, y2, x2, y2); + hidgl_add_triangle(&buffer, x2, y1, x2, y2, x1, y1); +} + +void hidgl_init(void) +{ + 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? */ + } +} + +int hidgl_stencil_bits(void) +{ + return stencil_bits; +} + +static void hidgl_clean_unassigned_stencil(void) +{ + glPushAttrib(GL_STENCIL_BUFFER_BIT); + glStencilMask(~assigned_bits); + glClearStencil(0); + glClear(GL_STENCIL_BUFFER_BIT); + glPopAttrib(); +} + +int hidgl_assign_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 */ + hidgl_clean_unassigned_stencil(); + assigned_bits |= first_dirty; + dirty_bits = assigned_bits; + + return first_dirty; +} + +void hidgl_return_stencil_bit(int bit) +{ + assigned_bits &= ~bit; +} + +void hidgl_reset_stencil_usage(void) +{ + assigned_bits = 0; + dirty_bits = 0; +} Index: tags/1.2.3/src_plugins/hid_gtk2_gl/hidgl.h =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/hidgl.h (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/hidgl.h (revision 8969) @@ -0,0 +1,79 @@ +/* + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#ifndef PCB_HID_COMMON_HIDGL_H +#define PCB_HID_COMMON_HIDGL_H + +#define TRIANGLE_ARRAY_SIZE 5461 +typedef struct { + GLfloat triangle_array[3 * 3 * TRIANGLE_ARRAY_SIZE]; + unsigned int triangle_count; + unsigned int coord_comp_count; +} triangle_buffer; + +extern triangle_buffer buffer; +extern float global_depth; + +void hidgl_init_triangle_array(triangle_buffer * buffer); +void hidgl_flush_triangles(triangle_buffer * buffer); +void hidgl_ensure_triangle_space(triangle_buffer * buffer, int count); + +static inline void +hidgl_add_triangle_3D(triangle_buffer * buffer, + GLfloat x1, GLfloat y1, GLfloat z1, + GLfloat x2, GLfloat y2, GLfloat z2, GLfloat x3, GLfloat y3, GLfloat z3) +{ + buffer->triangle_array[buffer->coord_comp_count++] = x1; + buffer->triangle_array[buffer->coord_comp_count++] = y1; + buffer->triangle_array[buffer->coord_comp_count++] = z1; + buffer->triangle_array[buffer->coord_comp_count++] = x2; + buffer->triangle_array[buffer->coord_comp_count++] = y2; + buffer->triangle_array[buffer->coord_comp_count++] = z2; + buffer->triangle_array[buffer->coord_comp_count++] = x3; + buffer->triangle_array[buffer->coord_comp_count++] = y3; + buffer->triangle_array[buffer->coord_comp_count++] = z3; + buffer->triangle_count++; +} + +static inline void +hidgl_add_triangle(triangle_buffer * buffer, GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2, GLfloat x3, GLfloat y3) +{ + hidgl_add_triangle_3D(buffer, x1, y1, global_depth, x2, y2, global_depth, x3, y3, global_depth); +} + +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_pcb_polygon(pcb_polygon_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); +int hidgl_stencil_bits(void); +int hidgl_assign_clear_stencil_bit(void); +void hidgl_return_stencil_bit(int bit); +void hidgl_reset_stencil_usage(void); + +#endif /* PCB_HID_COMMON_HIDGL_H */ Index: tags/1.2.3/src_plugins/hid_gtk2_gl/pcb.rc =================================================================== --- tags/1.2.3/src_plugins/hid_gtk2_gl/pcb.rc (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk2_gl/pcb.rc (revision 8969) @@ -0,0 +1 @@ +1 ICON "pcb_icon.ico" Index: tags/1.2.3/src_plugins/hid_gtk3_cairo/Makefile =================================================================== --- tags/1.2.3/src_plugins/hid_gtk3_cairo/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk3_cairo/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_gtk3_cairo + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/hid_gtk3_cairo/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/hid_gtk3_cairo/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk3_cairo/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk3_cairo/gtkhid-cairo.c (revision 8969) @@ -0,0 +1,1588 @@ +/* + * 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; + +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_surface_t *surface; /**< cairo surface for off-line painting */ + cairo_t *cr; /**< cairo context for off-line painting */ + cairo_t *cr_drawing_area; /**< cairo context connected to gport->drawing_area */ + + //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 attached_invalidate_depth; + int mark_invalidate_depth; +} render_priv_t; + +typedef struct hid_gc_s { + pcb_hid_t *me_pointer; + //cairo_t *cr; /**< cairo context */ + //cairo_surface_t *surface; /**< a surface */ + + const char *colorname; + pcb_coord_t width; + pcb_cap_style_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_); + +static const gchar *get_color_name(GdkRGBA * 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, GdkRGBA * 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); +} + +/** TODO: Does this function have some specifics in cairo ? or is it general ? */ +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].On) + 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].On; + + /* 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_cairo_destroy_gc(pcb_hid_gc_t gc) +{ + //if (gc->cr) + // //g_object_unref(gc->gc); + //if (gc->colorname != NULL) + // g_free(gc->colorname); + g_free(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; +} + +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(void) +{ + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr; + 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); + cairo_move_to(cr, points[i].x, points[i].y); + cairo_line_to(cr, points[i].x, points[i].y); + } + /*FIXME: problem: draw n points ... Efficiency ? */ + //gdk_draw_points(gport->drawable, priv->grid_gc, points, n); + +// 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. + } + 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; + 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); + } + + //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; + + 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(); + 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_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); +} + +#define WHICH_GC(gc) (cur_mask == HID_MASK_CLEAR ? priv->mask_gc : (gc)->gc) + +static void ghid_cairo_use_mask(pcb_mask_op_t use_it) +{ + static int mask_seq_id = 0; + GdkColor color; + render_priv_t *priv = gport->render_priv; + + if (use_it == cur_mask) + return; + switch (use_it) { + case HID_MASK_OFF: + //gport->drawable = gport->pixmap; + mask_seq = 0; + break; + + case HID_MASK_BEFORE: + /* The HID asks not to receive this mask type, so warn if we get it */ + g_return_if_reached(); + + case HID_MASK_CLEAR: + //if (!gport->mask) + // gport->mask = gdk_pixmap_new(0, gport->view.canvas_width, gport->view.canvas_height, 1); + //gport->drawable = gport->mask; + mask_seq = 0; + //if (!priv->mask_gc) { + // priv->mask_gc = gdk_gc_new(gport->drawable); + // gdk_gc_set_clip_origin(priv->mask_gc, 0, 0); + // set_clip(priv, priv->mask_gc); + //} + color.pixel = 1; + //gdk_gc_set_foreground(priv->mask_gc, &color); + //gdk_draw_rectangle(gport->drawable, priv->mask_gc, TRUE, 0, 0, gport->view.canvas_width, gport->view.canvas_height); + color.pixel = 0; + //gdk_gc_set_foreground(priv->mask_gc, &color); + break; + + case HID_MASK_AFTER: + mask_seq_id++; + if (!mask_seq_id) + mask_seq_id = 1; + mask_seq = mask_seq_id; + + //gport->drawable = gport->pixmap; + break; + + } + cur_mask = use_it; +} + + +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; + cairo_t *cr = priv->cr; + + if (cr == NULL) + return; + + 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) { + gdk_cairo_set_source_rgba(cr, &priv->bg_color); + //gdk_gc_set_foreground(gc->gc, &gport->bg_color); + } + else if (strcmp(name, "drill") == 0) { + 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); + //} + gdk_cairo_set_source_rgba(cr, &cc->color); + } +} + +static void ghid_cairo_set_line_cap(pcb_hid_gc_t gc, pcb_cap_style_t style) +{ + render_priv_t *priv = gport->render_priv; + cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT; + + if (priv->cr == NULL) + return; + + switch (style) { + case Trace_Cap: + case Round_Cap: + cap = CAIRO_LINE_CAP_ROUND; + gc->join = CAIRO_LINE_JOIN_ROUND; + break; + case Square_Cap: + case Beveled_Cap: + cap = CAIRO_LINE_CAP_SQUARE; + gc->join = CAIRO_LINE_JOIN_MITER; + break; + } + gc->cap = style; + + cairo_set_line_cap(priv->cr, cap); + cairo_set_line_join(priv->cr, gc->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) +{ + //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); + ghid_cairo_set_line_width(gc, gc->width); + ghid_cairo_set_line_cap(gc, (pcb_cap_style_t) gc->cap); + + //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; + + //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); +} + +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); +} + +static void ghid_cairo_fill_polygon(pcb_hid_gc_t gc, int n_coords, pcb_coord_t * x, pcb_coord_t * y) +{ + int i; + render_priv_t *priv = gport->render_priv; + cairo_t *cr = priv->cr; + int _x, _y; + + if (priv->cr == NULL) + return; + + USE_GC(gc); + + for (i = 0; i < n_coords; i++) { + _x = Vx(x[i]); + _y = Vy(y[i]); + if (i == 0) + cairo_move_to(cr, _x, _y); + else + cairo_line_to(cr, _x, _y); + } + cairo_fill(cr); +} + +static void 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 == 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.elem = 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; + } + + gdk_cairo_set_source_rgba(priv->cr, &priv->bg_color); + cairo_rectangle(priv->cr, 0.0, 0.0, gport->view.canvas_width, gport->view.canvas_height); + cairo_fill(priv->cr); + + 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(>k3_cairo_hid, &ctx); + ghid_cairo_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 = 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; + + 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 artefact. + */ + ghid_cairo_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_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; + 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->surface = NULL; + port->render_priv->cr = NULL; +} + +static void ghid_cairo_shutdown_renderer(void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + + cairo_surface_destroy(priv->surface); + priv->surface = NULL; + cairo_destroy(priv->cr); + priv->cr = NULL; + + g_free(port->render_priv); + port->render_priv = NULL; +} + +static void ghid_cairo_init_drawing_widget(GtkWidget * widget, void *vport) +{ +} + +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; + + 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(); + + done_once = 1; + } + + if (priv->surface) + cairo_surface_destroy(priv->surface); + + priv->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)); + if (priv->cr) + cairo_destroy(priv->cr); + priv->cr = cairo_create(priv->surface); + + //if (port->mask) { + // gdk_pixmap_unref(port->mask); + // port->mask = gdk_pixmap_new(0, port->view.canvas_width, port->view.canvas_height, 1); + //} +} + +/* GtkDrawingArea -> GtkWidget "draw" signal Call-Back function */ +static gboolean ghid_cairo_drawing_area_expose_cb(GtkWidget * widget, /*GdkEventExpose*/void * p, void *vport) +{ + GHidPort *port = vport; + render_priv_t *priv = port->render_priv; + cairo_t *cr = p; + //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); + //cairo_save(cr); + cairo_set_source_surface(cr, priv->surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + //cairo_restore(cr); + + priv->cr_drawing_area = cr; + + show_crosshair(TRUE); + + 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) +{ + //GHidPort *port = data; + //render_priv_t *priv = port->render_priv; + //cairo_surface_t *surf; + // + //surf = gdk_window_create_similar_surface(gtk_widget_get_window(widget), + // CAIRO_CONTENT_COLOR_ALPHA, + // gport->view.canvas_width, gport->view.canvas_height); + ////surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + //// gport->view.canvas_width, gport->view.canvas_height); + //priv->cr = cairo_create(surf); + //cairo_surface_destroy(surf); +} + +static gboolean ghid_cairo_preview_expose(GtkWidget * widget, GdkEventExpose * 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; /* 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; + + /* clear background */ + //cairo_rectangle(); + //cairo_fill(); + //gdk_draw_rectangle(window, priv->bg_gc, TRUE, 0, 0, allocation.width, allocation.height); + + /* call the drawing routine */ + expcall(>k3_cairo_hid, ctx); + + //gport->drawable = save_drawable; + gport->view = save_view; + gport->view.canvas_width = save_width; + gport->view.canvas_height = save_height; + + return FALSE; +} + +static void *ghid_cairo_render_pixmap(int cx, int cy, double zoom, int width, int height, int depth) +{ + GdkPixbuf *pixbuf; + //GdkDrawable *save_drawable; + //pcb_gtk_view_t save_view; + //int save_width, save_height; + //pcb_hid_expose_ctx_t ectx; + //render_priv *priv = gport->render_priv; + // + //save_drawable = gport->drawable; + //save_view = gport->view; + //save_width = gport->view.canvas_width; + //save_height = gport->view.canvas_height; + // + //pixmap = gdk_pixmap_new(NULL, width, height, depth); + // + ///* Setup drawable and zoom factor for drawing routines + // */ + // + //gport->drawable = pixmap; + //gport->view.coord_per_px = zoom; + //gport->view.canvas_width = width; + //gport->view.canvas_height = height; + //gport->view.width = width * gport->view.coord_per_px; + //gport->view.height = height * gport->view.coord_per_px; + //gport->view.x0 = conf_core.editor.view.flip_x ? PCB->MaxWidth - cx : cx; + //gport->view.x0 -= gport->view.height / 2; + //gport->view.y0 = conf_core.editor.view.flip_y ? PCB->MaxHeight - cy : cy; + //gport->view.y0 -= gport->view.width / 2; + // + ///* clear background */ + //gdk_draw_rectangle(pixmap, priv->bg_gc, TRUE, 0, 0, width, height); + // + ///* call the drawing routine */ + //ectx.view.X1 = MIN(Px(0), Px(gport->view.canvas_width + 1)); + //ectx.view.Y1 = MIN(Py(0), Py(gport->view.canvas_height + 1)); + //ectx.view.X2 = MAX(Px(0), Px(gport->view.canvas_width + 1)); + //ectx.view.Y2 = MAX(Py(0), Py(gport->view.canvas_height + 1)); + // + //ectx.view.X1 = MAX(0, MIN(PCB->MaxWidth, ectx.view.X1)); + //ectx.view.X2 = MAX(0, MIN(PCB->MaxWidth, ectx.view.X2)); + //ectx.view.Y1 = MAX(0, MIN(PCB->MaxHeight, ectx.view.Y1)); + //ectx.view.Y2 = MAX(0, MIN(PCB->MaxHeight, ectx.view.Y2)); + // + //ectx.force = 0; + //ectx.content.elem = NULL; + // + //pcb_hid_expose_all(>k3_cairo_hid, &ectx); + // + //gport->drawable = save_drawable; + //gport->view = save_view; + //gport->view.canvas_width = save_width; + //gport->view.canvas_height = save_height; + + return pixbuf; +} + +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->render_pixmap = ghid_cairo_render_pixmap; + 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->make_gc = ghid_cairo_make_gc; + hid->destroy_gc = ghid_cairo_destroy_gc; + hid->use_mask = ghid_cairo_use_mask; + 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_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.3/src_plugins/hid_gtk3_cairo/gtkhid-main.c =================================================================== --- tags/1.2.3/src_plugins/hid_gtk3_cairo/gtkhid-main.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk3_cairo/gtkhid-main.c (revision 8969) @@ -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_cairo_cookie = "gtk3 hid, cairo"; +const char *ghid_cairo_menu_cookie = "gtk3 hid menu, cairo"; + +pcb_hid_t gtk3_cairo_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.3/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup =================================================================== --- tags/1.2.3/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (nonexistent) +++ tags/1.2.3/src_plugins/hid_gtk3_cairo/hid_gtk3_cairo.pup (revision 8969) @@ -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.3/src_plugins/hid_lesstif/Makefile =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/Makefile (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/Makefile (revision 8969) @@ -0,0 +1,6 @@ +all: + cd ../../src && $(MAKE) mod_hid_lesstif + +clean: + rm *.o *.so 2>/dev/null ; true + Index: tags/1.2.3/src_plugins/hid_lesstif/Plug.tmpasm =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/Plug.tmpasm (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/Plug.tmpasm (revision 8969) @@ -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.3/src_plugins/hid_lesstif/dialogs.c =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/dialogs.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/dialogs.c (revision 8969) @@ -0,0 +1,1718 @@ +#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(Widget w, void *v, void *cbs) +{ + ok = (int) (size_t) v; +} + +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, (XtPointer) 1); + XtAddCallback(fsb, XmNcancelCallback, (XtCallbackProc) dialog_callback, (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, (XtPointer) 0); + XtAddCallback(confirm_dialog, XmNokCallback, (XtCallbackProc) dialog_callback, (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, (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) +{ + Widget dialog, topform; + stdarg_n = 0; + dialog = XmCreateQuestionDialog(mainwind, XmStrCast(name), stdarg_args, stdarg_n); + + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_SYMBOL_LABEL)); + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_MESSAGE_LABEL)); + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_HELP_BUTTON)); + XtAddCallback(dialog, XmNcancelCallback, (XtCallbackProc) dialog_callback, (XtPointer) 0); + if (ok) + XtAddCallback(dialog, XmNokCallback, (XtCallbackProc) dialog_callback, (XtPointer) 1); + else + XtUnmanageChild(XmMessageBoxGetChild(dialog, XmDIALOG_OK_BUTTON)); + + stdarg_n = 0; + topform = XmCreateForm(dialog, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(topform); + return topform; +} + +int lesstif_attribute_dialog(pcb_hid_attribute_t * attrs, int n_attrs, pcb_hid_attr_val_t * results, const char *title, const char *descr) +{ + Widget dialog, topform, lform, form; + Widget *wl; + int i, rv; + static XmString empty = 0; + int actual_nattrs = 0; + int attrcount = 0; + + if (!empty) + empty = XmStringCreatePCB(" "); + + for (i = 0; i < n_attrs; i++) { + if (attrs[i].help_text != ATTR_UNDOCUMENTED) + actual_nattrs++; + results[i] = attrs[i].default_val; + if (results[i].str_value) + results[i].str_value = pcb_strdup(results[i].str_value); + } + + wl = (Widget *) malloc(n_attrs * sizeof(Widget)); + + topform = create_form_ok_dialog(title, 1); + dialog = XtParent(topform); + + stdarg_n = 0; + stdarg(XmNfractionBase, n_attrs); + XtSetValues(topform, stdarg_args, stdarg_n); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNfractionBase, actual_nattrs); + lform = XmCreateForm(topform, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(lform); + + stdarg_n = 0; + stdarg(XmNtopAttachment, XmATTACH_FORM); + stdarg(XmNbottomAttachment, XmATTACH_FORM); + stdarg(XmNleftAttachment, XmATTACH_WIDGET); + stdarg(XmNleftWidget, lform); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNfractionBase, actual_nattrs); + form = XmCreateForm(topform, XmStrCast("attributes"), stdarg_args, stdarg_n); + XtManageChild(form); + + attrcount = -1; + for (i = 0; i < n_attrs; i++) { + Widget w; + + if (attrs[i].help_text == ATTR_UNDOCUMENTED) + continue; + attrcount++; + + stdarg_n = 0; + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_POSITION); + stdarg(XmNtopPosition, attrcount); + stdarg(XmNbottomAttachment, XmATTACH_POSITION); + stdarg(XmNbottomPosition, attrcount + 1); + stdarg(XmNalignment, XmALIGNMENT_END); + w = XmCreateLabel(lform, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + XtManageChild(w); + } + + attrcount = -1; + for (i = 0; i < n_attrs; i++) { + static char buf[30]; + stdarg_n = 0; + + if (attrs[i].help_text == ATTR_UNDOCUMENTED) + continue; + attrcount++; + + stdarg(XmNleftAttachment, XmATTACH_FORM); + stdarg(XmNrightAttachment, XmATTACH_FORM); + stdarg(XmNtopAttachment, XmATTACH_POSITION); + stdarg(XmNtopPosition, attrcount); + stdarg(XmNbottomAttachment, XmATTACH_POSITION); + stdarg(XmNbottomPosition, attrcount + 1); + stdarg(XmNalignment, XmALIGNMENT_END); + + switch (attrs[i].type) { + case PCB_HATT_LABEL: + stdarg(XmNlabelString, empty); + wl[i] = XmCreateLabel(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_BOOL: + stdarg(XmNlabelString, empty); + stdarg(XmNset, results[i].int_value); + wl[i] = XmCreateToggleButton(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_STRING: + stdarg(XmNcolumns, 40); + stdarg(XmNresizeWidth, True); + stdarg(XmNvalue, results[i].str_value); + wl[i] = XmCreateTextField(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_INTEGER: + stdarg(XmNcolumns, 13); + stdarg(XmNresizeWidth, True); + sprintf(buf, "%d", results[i].int_value); + stdarg(XmNvalue, buf); + wl[i] = XmCreateTextField(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_COORD: + stdarg(XmNcolumns, 13); + stdarg(XmNresizeWidth, True); + pcb_snprintf(buf, sizeof(buf), "%$mS", results[i].coord_value); + stdarg(XmNvalue, buf); + wl[i] = XmCreateTextField(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + break; + case PCB_HATT_REAL: + stdarg(XmNcolumns, 16); + stdarg(XmNresizeWidth, True); + pcb_snprintf(buf, sizeof(buf), "%g", results[i].real_value); + stdarg(XmNvalue, buf); + wl[i] = XmCreateTextField(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + 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(form, XmStrCast(attrs[i].name), stdarg_args + sn, stdarg_n - sn); + + stdarg_n = sn; + stdarg(XmNlabelString, empty); + stdarg(XmNsubMenuId, submenu); + wl[i] = XmCreateOptionMenu(form, XmStrCast(attrs[i].name), stdarg_args, stdarg_n); + + for (sn = 0; attrs[i].enumerations[sn]; sn++) { + Widget btn; + XmString label; + stdarg_n = 0; + label = XmStringCreatePCB(attrs[i].enumerations[sn]); + stdarg(XmNuserData, &attrs[i].enumerations[sn]); + stdarg(XmNlabelString, label); + btn = XmCreatePushButton(submenu, XmStrCast("menubutton"), stdarg_args, stdarg_n); + XtManageChild(btn); + XmStringFree(label); + if (sn == attrs[i].default_val.int_value) + default_button = btn; + } + if (default_button) { + stdarg_n = 0; + stdarg(XmNmenuHistory, default_button); + XtSetValues(wl[i], stdarg_args, stdarg_n); + } + } + break; + default: + wl[i] = XmCreateLabel(form, XmStrCast("UNIMPLEMENTED"), stdarg_args, stdarg_n); + break; + } + + XtManageChild(wl[i]); + } + + rv = wait_for_dialog(dialog); + + for (i = 0; i < n_attrs; i++) { + char *cp; + + if (attrs[i].help_text == ATTR_UNDOCUMENTED) + continue; + + switch (attrs[i].type) { + case PCB_HATT_BOOL: + results[i].int_value = XmToggleButtonGetState(wl[i]); + break; + case PCB_HATT_STRING: + results[i].str_value = XmTextGetString(wl[i]); + break; + case PCB_HATT_INTEGER: + cp = XmTextGetString(wl[i]); + sscanf(cp, "%d", &results[i].int_value); + break; + case PCB_HATT_COORD: + cp = XmTextGetString(wl[i]); + results[i].coord_value = pcb_get_value(cp, NULL, NULL, NULL); + break; + case PCB_HATT_REAL: + cp = XmTextGetString(wl[i]); + sscanf(cp, "%lg", &results[i].real_value); + break; + case PCB_HATT_ENUM: + { + const char **uptr; + Widget btn; + + stdarg_n = 0; + stdarg(XmNmenuHistory, &btn); + XtGetValues(wl[i], stdarg_args, stdarg_n); + stdarg_n = 0; + stdarg(XmNuserData, &uptr); + XtGetValues(btn, stdarg_args, stdarg_n); + results[i].int_value = uptr - attrs[i].enumerations; + } + break; + default: + break; + } + } + + free(wl); + XtDestroyWidget(dialog); + + return rv ? 0 : 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", "")) { + 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")) + 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); + 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, (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)) { + 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, (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, (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 */ + for (i = 0; i < attributes_list->Number; i++) { + if (attributes_list->List[i].name) + free(attributes_list->List[i].name); + if (attributes_list->List[i].value) + free(attributes_list->List[i].value); + } + if (attributes_list->Max < attr_num_rows) { + int sz = attr_num_rows * sizeof(pcb_attribute_t); + if (attributes_list->List == NULL) + attributes_list->List = (pcb_attribute_t *) malloc(sz); + else + attributes_list->List = (pcb_attribute_t *) realloc(attributes_list->List, sz); + attributes_list->Max = attr_num_rows; + } + for (i = 0; i < attr_num_rows; i++) { + attributes_list->List[i].name = pcb_strdup(XmTextFieldGetString(attr_row[i].w_name)); + attributes_list->List[i].value = pcb_strdup(XmTextFieldGetString(attr_row[i].w_value)); + attributes_list->Number = attr_num_rows; + } + } + + 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.3/src_plugins/hid_lesstif/dlg_preview.c =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/dlg_preview.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/dlg_preview.c (revision 8969) @@ -0,0 +1,361 @@ +/* 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 + +#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; \ + pixmap = XCreatePixmap(XtDisplay(da), XtWindow(da), pd->v_width, pd->v_height, widget_depth(da)); \ + view_left_x = pd->y; \ + view_top_y = pd->x; \ + view_zoom = pd->zoom; \ + view_width = pd->v_width; \ + view_height = pd->v_height; \ + use_mask = 0; \ + 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 { \ + XGCValues gcv; \ + GC gc; \ + memset(&gcv, 0, sizeof(gcv)); \ + gcv.graphics_exposures = 0; \ + gc = XtGetGC(da, GCGraphicsExposures, &gcv); \ + view_left_x = save_vx; \ + view_top_y = save_vy; \ + view_zoom = save_vz; \ + view_width = save_vw; \ + view_height = save_vh; \ + XCopyArea(lesstif_display, pixmap, XtWindow(da), gc, 0, 0, pd->v_width, pd->v_height, 0, 0); \ + XtReleaseGC(da, gc); \ + XFreePixmap(lesstif_display, pixmap); \ + 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 { \ + XFillRectangle(display, pixmap, bg_gc, 0, 0, pd->v_width, pd->v_height); \ + pcb_hid_expose_layer(&lesstif_hid, &pd->ctx); \ +} 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_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_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_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.3/src_plugins/hid_lesstif/hid_lesstif.pup =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/hid_lesstif.pup (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/hid_lesstif.pup (revision 8969) @@ -0,0 +1,9 @@ +$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 +autoload 1 Index: tags/1.2.3/src_plugins/hid_lesstif/lesstif.h =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/lesstif.h (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/lesstif.h (revision 8969) @@ -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.3/src_plugins/hid_lesstif/library.c =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/library.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/library.c (revision 8969) @@ -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 "vtptr.h" +#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; + +vtptr_t picks; /* of pcb_fplibrary_t * */ +vtptr_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) { + vtptr_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); + vtptr_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]); + + vtptr_truncate(&picks, 0); + vtptr_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.3/src_plugins/hid_lesstif/main.c =================================================================== --- tags/1.2.3/src_plugins/hid_lesstif/main.c (nonexistent) +++ tags/1.2.3/src_plugins/hid_lesstif/main.c (revision 8969) @@ -0,0 +1,3825 @@ +/* 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 + +#ifdef HAVE_UNISTD_H +#include +#endif + +#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 "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; + +/* The first is the "current" pixmap. The main_ is the real one we + usually use, the mask_ are the ones for doing polygon masks. The + pixmap is the saved pixels, the bitmap is for the "erase" color. + We set pixmap to point to main_pixmap or mask_pixmap as needed. */ +static Pixmap pixmap = 0; +static Pixmap main_pixmap = 0; +static Pixmap mask_pixmap = 0; +static Pixmap mask_bitmap = 0; +static int use_mask = 0; + +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_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 void lesstif_use_mask(pcb_mask_op_t use_it); +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 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].On) + 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 = 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; + 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 0 + 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 < 0) + view_left_x = 0; + if (view_top_y < 0) + view_top_y = 0; + if (view_width * view_zoom > PCB->MaxWidth && view_height * view_zoom > PCB->MaxHeight) { + zoom_by(1, 0, 0); + return; + } +#endif + + 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_char, char *out, int out_len) +{ + char *name = XKeysymToString(key_char); + 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