aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-10-18 04:32:43 +0000
committerHans-Christoph Steiner <eighthave@users.sourceforge.net>2011-10-18 04:32:43 +0000
commit2bc707741a9d61495938a94d5ca868a603902562 (patch)
treecdad6d1f574c80e80df44533e9d02546d8556e12
new 'flatgui' lib made from the GUI objects of the old 'flatspace' libsvn2git-root
svn path=/trunk/externals/flatgui/; revision=15612
-rw-r--r--LICENSE.txt676
-rw-r--r--Makefile410
-rw-r--r--README.txt3
-rw-r--r--TODO.txt3
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control21
-rw-r--r--debian/copyright23
-rw-r--r--debian/gbp.conf7
-rw-r--r--debian/links3
-rwxr-xr-xdebian/rules17
-rw-r--r--debian/source/format1
-rw-r--r--debian/watch2
-rw-r--r--entry-help.pd148
-rw-r--r--entry.c848
-rw-r--r--examples/clock.pd38
-rw-r--r--flatgui-meta.pd7
-rw-r--r--knob-help.pd15
-rw-r--r--knob.c793
-rw-r--r--popup-help.pd39
-rw-r--r--popup.c701
-rw-r--r--template-meta.pd6
22 files changed, 3767 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..4432540
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,676 @@
+
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. 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
+them 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 prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. 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.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey 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;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If 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 convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU 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 that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ 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.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+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.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ 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
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU 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 <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program 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, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a65da8e
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,410 @@
+## Pd library template version 1.0.11
+# For instructions on how to use this template, see:
+# http://puredata.info/docs/developer/MakefileTemplate
+LIBRARY_NAME = flatgui
+
+# add your .c source files, one object per file, to the SOURCES
+# variable, help files will be included automatically, and for GUI
+# objects, the matching .tcl file too
+SOURCES = entry.c knob.c popup.c
+
+# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
+# be included automatically
+PDOBJECTS =
+
+# example patches and related files, in the 'examples' subfolder
+EXAMPLES = clock.pd
+
+# manuals and related files, in the 'manual' subfolder
+MANUAL =
+
+# if you want to include any other files in the source and binary tarballs,
+# list them here. This can be anything from header files, test patches,
+# documentation, etc. README.txt and LICENSE.txt are required and therefore
+# automatically included
+EXTRA_DIST =
+
+
+
+#------------------------------------------------------------------------------#
+#
+# things you might need to edit if you are using other C libraries
+#
+#------------------------------------------------------------------------------#
+
+ALL_CFLAGS = -I"$(PD_INCLUDE)"
+ALL_LDFLAGS =
+SHARED_LDFLAGS =
+ALL_LIBS =
+
+
+#------------------------------------------------------------------------------#
+#
+# you shouldn't need to edit anything below here, if we did it right :)
+#
+#------------------------------------------------------------------------------#
+
+# these can be set from outside without (usually) breaking the build
+CFLAGS = -Wall -W -g
+LDFLAGS =
+LIBS =
+
+# get library version from meta file
+LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd)
+
+ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"'
+
+PD_INCLUDE = $(PD_PATH)/include/pd
+# where to install the library, overridden below depending on platform
+prefix = /usr/local
+libdir = $(prefix)/lib
+pkglibdir = $(libdir)/pd-externals
+objectsdir = $(pkglibdir)
+
+INSTALL = install
+INSTALL_PROGRAM = $(INSTALL) -p -m 644
+INSTALL_DATA = $(INSTALL) -p -m 644
+INSTALL_DIR = $(INSTALL) -p -m 755 -d
+
+ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
+ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
+
+DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION)
+
+UNAME := $(shell uname -s)
+ifeq ($(UNAME),Darwin)
+ CPU := $(shell uname -p)
+ ifeq ($(CPU),arm) # iPhone/iPod Touch
+ SOURCES += $(SOURCES_iphoneos)
+ EXTENSION = pd_darwin
+ SHARED_EXTENSION = dylib
+ OS = iphoneos
+ PD_PATH = /Applications/Pd-extended.app/Contents/Resources
+ IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
+ CC=$(IPHONE_BASE)/gcc
+ CPP=$(IPHONE_BASE)/cpp
+ CXX=$(IPHONE_BASE)/g++
+ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
+ IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
+ OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS)
+ ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
+ SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT)
+ ALL_LIBS += -lc $(LIBS_iphoneos)
+ STRIP = strip -x
+ DISTBINDIR=$(DISTDIR)-$(OS)
+ else # Mac OS X
+ SOURCES += $(SOURCES_macosx)
+ EXTENSION = pd_darwin
+ SHARED_EXTENSION = dylib
+ OS = macosx
+ PD_PATH = /Applications/Pd-extended.app/Contents/Resources
+ OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
+# build universal 32-bit on 10.4 and 32/64 on newer
+ ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8)
+ FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4
+ else
+ FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4
+ SOURCES += $(SOURCES_iphoneos)
+ endif
+ ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include
+ # if the 'pd' binary exists, check the linking against it to aid with stripping
+ BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd)
+ ALL_LDFLAGS += $(FAT_FLAGS) -bundle $(BUNDLE_LOADER) -undefined dynamic_lookup -L/sw/lib
+ SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \
+ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0
+ ALL_LIBS += -lc $(LIBS_macosx)
+ STRIP = strip -x
+ DISTBINDIR=$(DISTDIR)-$(OS)
+# install into ~/Library/Pd on Mac OS X since /usr/local isn't used much
+ pkglibdir=$(HOME)/Library/Pd
+ endif
+endif
+# Tho Android uses Linux, we use this fake uname to provide an easy way to
+# setup all this things needed to cross-compile for Android using the NDK
+ifeq ($(UNAME),ANDROID)
+ CPU := arm
+ SOURCES += $(SOURCES_android)
+ EXTENSION = pd_linux
+ SHARED_EXTENSION = so
+ OS = android
+ PD_PATH = /usr
+ NDK_BASE := /usr/local/android-ndk
+ NDK_PLATFORM_VERSION := 5
+ NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm
+ NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]')
+ NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86
+ CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT)
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ CFLAGS +=
+ LDFLAGS += -rdynamic -shared
+ SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
+ LIBS += -lc $(LIBS_android)
+ STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \
+ --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),Linux)
+ CPU := $(shell uname -m)
+ SOURCES += $(SOURCES_linux)
+ EXTENSION = pd_linux
+ SHARED_EXTENSION = so
+ OS = linux
+ PD_PATH = /usr
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS += -fPIC
+ ALL_LDFLAGS += -rdynamic -shared -fPIC
+ SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
+ ALL_LIBS += -lc $(LIBS_linux)
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),GNU)
+ # GNU/Hurd, should work like GNU/Linux for basically all externals
+ CPU := $(shell uname -m)
+ SOURCES += $(SOURCES_linux)
+ EXTENSION = pd_linux
+ SHARED_EXTENSION = so
+ OS = linux
+ PD_PATH = /usr
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS += -fPIC
+ ALL_LDFLAGS += -rdynamic -shared -fPIC
+ SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+ ALL_LIBS += -lc $(LIBS_linux)
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),GNU/kFreeBSD)
+ # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals
+ CPU := $(shell uname -m)
+ SOURCES += $(SOURCES_linux)
+ EXTENSION = pd_linux
+ SHARED_EXTENSION = so
+ OS = linux
+ PD_PATH = /usr
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS += -fPIC
+ ALL_LDFLAGS += -rdynamic -shared -fPIC
+ SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+ ALL_LIBS += -lc $(LIBS_linux)
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
+ CPU := $(shell uname -m)
+ SOURCES += $(SOURCES_cygwin)
+ EXTENSION = dll
+ SHARED_EXTENSION = dll
+ OS = cygwin
+ PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd
+ OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS +=
+ ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin"
+ SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+ ALL_LIBS += -lc -lpd $(LIBS_cygwin)
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+ifeq (MINGW,$(findstring MINGW,$(UNAME)))
+ CPU := $(shell uname -m)
+ SOURCES += $(SOURCES_windows)
+ EXTENSION = dll
+ SHARED_EXTENSION = dll
+ OS = windows
+ PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd)
+ # MinGW doesn't seem to include cc so force gcc
+ CC=gcc
+ OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
+ ALL_CFLAGS += -mms-bitfields
+ ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj"
+ SHARED_LDFLAGS += -shared
+ ALL_LIBS += -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 $(LIBS_windows)
+ STRIP = strip --strip-unneeded -R .note -R .comment
+ DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+
+# in case somebody manually set the HELPPATCHES above
+HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
+
+ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS)
+ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS)
+ALL_LIBS := $(LIBS) $(ALL_LIBS)
+
+SHARED_SOURCE ?= $(shell test ! -e lib$(LIBRARY_NAME).c || \
+ echo lib$(LIBRARY_NAME).c )
+SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h)
+SHARED_LIB = $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION))
+
+.PHONY = install libdir_install single_install install-doc install-examples install-manual clean distclean dist etags $(LIBRARY_NAME)
+
+all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB)
+
+%.o: %.c
+ $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c"
+
+%.$(EXTENSION): %.o $(SHARED_LIB)
+ $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB)
+ chmod a-x "$*.$(EXTENSION)"
+
+# this links everything into a single binary file
+$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o
+ $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) $(LIBRARY_NAME).o $(ALL_LIBS)
+ chmod a-x $(LIBRARY_NAME).$(EXTENSION)
+
+$(SHARED_LIB): $(SHARED_SOURCE:.c=.o)
+ $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(LIBS)
+
+install: libdir_install
+
+# The meta and help files are explicitly installed to make sure they are
+# actually there. Those files are not optional, then need to be there.
+libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(SOURCES))" || (\
+ $(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
+ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
+ test -z "$(strip $(SHARED_LIB))" || \
+ $(INSTALL_DATA) $(SHARED_LIB) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \
+ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_DATA) $(PDOBJECTS) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+
+# install library linked as single binary
+single_install: $(LIBRARY_NAME) install-doc install-examples install-manual
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
+
+install-doc:
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \
+ $(INSTALL_DATA) $(HELPPATCHES) \
+ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+ $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt
+ $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt
+
+install-examples:
+ test -z "$(strip $(EXAMPLES))" || \
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
+ for file in $(EXAMPLES); do \
+ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \
+ done
+
+install-manual:
+ test -z "$(strip $(MANUAL))" || \
+ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \
+ for file in $(MANUAL); do \
+ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \
+ done
+
+
+clean:
+ -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o)
+ -rm -f -- $(SOURCES:.c=.$(EXTENSION))
+ -rm -f -- $(LIBRARY_NAME).o
+ -rm -f -- $(LIBRARY_NAME).$(EXTENSION)
+ -rm -f -- $(SHARED_LIB)
+
+distclean: clean
+ -rm -f -- $(DISTBINDIR).tar.gz
+ -rm -rf -- $(DISTBINDIR)
+ -rm -f -- $(DISTDIR).tar.gz
+ -rm -rf -- $(DISTDIR)
+ -rm -f -- $(ORIGDIR).tar.gz
+ -rm -rf -- $(ORIGDIR)
+
+
+$(DISTBINDIR):
+ $(INSTALL_DIR) $(DISTBINDIR)
+
+libdir: all $(DISTBINDIR)
+ $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR)
+ $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR)
+ $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR)
+ test -z "$(strip $(EXTRA_DIST))" || \
+ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR)
+# tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
+
+$(DISTDIR):
+ $(INSTALL_DIR) $(DISTDIR)
+
+$(ORIGDIR):
+ $(INSTALL_DIR) $(ORIGDIR)
+
+dist: $(DISTDIR)
+ $(INSTALL_DATA) Makefile $(DISTDIR)
+ $(INSTALL_DATA) README.txt $(DISTDIR)
+ $(INSTALL_DATA) LICENSE.txt $(DISTDIR)
+ $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR)
+ test -z "$(strip $(ALLSOURCES))" || \
+ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR)
+ test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \
+ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR)
+ test -z "$(strip $(SHARED_HEADER))" || \
+ $(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR)
+ test -z "$(strip $(SHARED_SOURCE))" || \
+ $(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR)
+ test -z "$(strip $(PDOBJECTS))" || \
+ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR)
+ test -z "$(strip $(HELPPATCHES))" || \
+ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR)
+ test -z "$(strip $(EXTRA_DIST))" || \
+ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR)
+ test -z "$(strip $(EXAMPLES))" || \
+ $(INSTALL_DIR) $(DISTDIR)/examples && \
+ for file in $(EXAMPLES); do \
+ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \
+ done
+ test -z "$(strip $(MANUAL))" || \
+ $(INSTALL_DIR) $(DISTDIR)/manual && \
+ for file in $(MANUAL); do \
+ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \
+ done
+ tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
+
+# make a Debian source package
+dpkg-source:
+ debclean
+ make distclean dist
+ mv $(DISTDIR) $(ORIGDIR)
+ tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR)
+ rm -f -- $(DISTDIR).tar.gz
+ rm -rf -- $(DISTDIR) $(ORIGDIR)
+ cd .. && dpkg-source -b $(LIBRARY_NAME)
+
+etags:
+ etags *.h $(SOURCES) ../../pd/src/*.[ch] /usr/include/*.h /usr/include/*/*.h
+
+showsetup:
+ @echo "CC: $(CC)"
+ @echo "CFLAGS: $(CFLAGS)"
+ @echo "LDFLAGS: $(LDFLAGS)"
+ @echo "LIBS: $(LIBS)"
+ @echo "ALL_CFLAGS: $(ALL_CFLAGS)"
+ @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)"
+ @echo "ALL_LIBS: $(ALL_LIBS)"
+ @echo "PD_INCLUDE: $(PD_INCLUDE)"
+ @echo "PD_PATH: $(PD_PATH)"
+ @echo "objectsdir: $(objectsdir)"
+ @echo "LIBRARY_NAME: $(LIBRARY_NAME)"
+ @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)"
+ @echo "SOURCES: $(SOURCES)"
+ @echo "SHARED_HEADER: $(SHARED_HEADER)"
+ @echo "SHARED_SOURCE: $(SHARED_SOURCE)"
+ @echo "SHARED_LIB: $(SHARED_LIB)"
+ @echo "PDOBJECTS: $(PDOBJECTS)"
+ @echo "ALLSOURCES: $(ALLSOURCES)"
+ @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))"
+ @echo "UNAME: $(UNAME)"
+ @echo "CPU: $(CPU)"
+ @echo "pkglibdir: $(pkglibdir)"
+ @echo "DISTDIR: $(DISTDIR)"
+ @echo "ORIGDIR: $(ORIGDIR)"
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..11692fb
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,3 @@
+
+flatgui is a library of GUI objects that were part of the old
+'flatspace' collection that was discontinued.
diff --git a/TODO.txt b/TODO.txt
new file mode 100644
index 0000000..f3350ce
--- /dev/null
+++ b/TODO.txt
@@ -0,0 +1,3 @@
+
+- implement CPPFLAGS for all -I include statements, and replace PD_INCLUDE with that
+http://stackoverflow.com/questions/2754966/cflags-vs-cppflags
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..9d53a4c
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,5 @@
+pd-template (0.0-1) unstable; urgency=low
+
+ * Initial release (Closes: #nnnn) <nnnn is the bug number of your ITP>
+
+ -- Hans-Christoph Steiner <hans@eds.org> Thu, 21 Jan 2010 23:27:04 -0500
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..64d96f8
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,21 @@
+Source: pd-template
+Section: sound
+Priority: optional
+Maintainer: Debian Multimedia Maintainers <pkg-multimedia-maintainers@lists.alioth.debian.org>
+DM-Upload-Allowed: yes
+Uploaders: Hans-Christoph Steiner <hans@eds.org>
+Build-Depends: debhelper (>= 7.0.50~),
+ puredata-dev | puredata (<< 0.43)
+Standards-Version: 3.9.2
+Homepage: http://puredata.info
+Vcs-Git: git://git.debian.org/pkg-multimedia/pd-template.git
+Vcs-Browser: http://git.debian.org/?p=pkg-multimedia/pd-template.git;a=summary
+
+Package: pd-template
+Architecture: any
+Depends: ${shlibs:Depends},
+ pd,
+ pd-libdir,
+ ${misc:Depends}
+Recommends: pd-import
+Description:
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..bf20b3b
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,23 @@
+Format-Specification: http://svn.debian.org/wsvn/dep/web/deps/dep5.mdwn?rev=135
+Name: template
+Maintainer:
+Source: http://sourceforge.net/projects/pure-data/files/libraries/template/
+
+Files: *
+Copyright: 2001-2003, Free Software Foundation
+License: GPL-2+
+ This package is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+ .
+ This package is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+ .
+ You should have received a copy of the GNU General Public License
+ along with this package; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+X-Comment: On Debian systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL-2'.
diff --git a/debian/gbp.conf b/debian/gbp.conf
new file mode 100644
index 0000000..ae1dc36
--- /dev/null
+++ b/debian/gbp.conf
@@ -0,0 +1,7 @@
+[DEFAULT]
+upstream-branch = upstream
+debian-branch = master
+upstream-tag = upstream/%(version)s
+debian-tag = debian/%(version)s
+pristine-tar = True
+sign-tags = True
diff --git a/debian/links b/debian/links
new file mode 100644
index 0000000..e21d901
--- /dev/null
+++ b/debian/links
@@ -0,0 +1,3 @@
+usr/lib/pd/extra/template/README.txt usr/share/doc/pd-template/README
+usr/lib/pd/extra/template/examples usr/share/doc/pd-template/examples
+usr/share/common-licenses/GPL-2 usr/lib/pd/extra/template/LICENSE.txt
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..df5d06a
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,17 @@
+#!/usr/bin/make -f
+
+LIBRARY_NAME = template
+PACKAGE = pd-$(LIBRARY_NAME)
+pkglibdir = /usr/lib/pd/extra
+
+%:
+ dh $@ --buildsystem=makefile
+
+override_dh_auto_install:
+ dh_auto_install -- prefix=/usr pkglibdir=$(pkglibdir)
+# replace license file with link to the Debian license file
+ rm -f -- $(CURDIR)/debian/$(PACKAGE)/$(pkglibdir)/$(LIBRARY_NAME)/LICENSE.txt
+
+override_dh_shlibdeps:
+ dpkg-shlibdeps $(CURDIR)/debian/$(PACKAGE)$(pkglibdir)/$(LIBRARY_NAME)/*.pd_linux \
+ -T$(CURDIR)/debian/$(PACKAGE).substvars
diff --git a/debian/source/format b/debian/source/format
new file mode 100644
index 0000000..163aaf8
--- /dev/null
+++ b/debian/source/format
@@ -0,0 +1 @@
+3.0 (quilt)
diff --git a/debian/watch b/debian/watch
new file mode 100644
index 0000000..82c0d1a
--- /dev/null
+++ b/debian/watch
@@ -0,0 +1,2 @@
+version=3
+http://sf.net/pure-data/template-(.*)\.tar\.gz
diff --git a/entry-help.pd b/entry-help.pd
new file mode 100644
index 0000000..170e9d2
--- /dev/null
+++ b/entry-help.pd
@@ -0,0 +1,148 @@
+#N canvas 216 22 793 604 10;
+#X obj 72 208 entry 150 100 grey yellow;
+#X obj 11 84 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1
+-1;
+#X obj 32 316 print;
+#X msg 109 73 clear;
+#X msg 127 94 set one two three four five six;
+#X msg 31 29 fgcolour yellow;
+#X msg 94 4 bgcolour purple;
+#X obj 29 526 entry 155 48 grey70 purple;
+#X text 9 355 Creation arguments are: width height bgcolor fgcolor.
+The width and height are in pixels.;
+#X obj 251 254 select return;
+#X obj 79 317 pddp/print;
+#X obj 218 165 trigger bang bang;
+#X msg 218 186 clear;
+#X symbolatom 216 319 10 0 0 1 last_key_typed - -;
+#X text 255 275 ^-- hit return to output;
+#X msg 123 490 size 400 200;
+#X msg 6 4 bgcolour grey;
+#X msg 52 52 fgcolour black;
+#X text 12 396 The size message currently only takes affect after a
+save and reopen.;
+#X msg 138 117 append seven eight nine;
+#X msg 142 137 append ten eleven.;
+#X msg 30 459 fontsize \$1;
+#X msg 52 432 12;
+#X msg 20 431 9;
+#X msg 85 429 98;
+#X obj 148 31 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/text.htm
+;
+#X obj 395 132 entry 300 50 grey70 black;
+#X msg 571 101 option relief \$1;
+#X obj 570 80 symbol;
+#X msg 468 45 flat;
+#X msg 503 45 groove;
+#X msg 550 45 raised;
+#X msg 598 44 ridge;
+#X msg 639 44 solid;
+#X msg 680 44 sunken;
+#X obj 610 233 symbol;
+#X msg 591 208 normal;
+#X msg 637 208 disabled;
+#X msg 609 256 option state \$1;
+#X msg 124 465 size 100 50;
+#X text 663 235 disable editing;
+#X obj 448 297 entry 250 80 grey70 black;
+#X obj 440 200 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144
+-1 -1 0 1;
+#X obj 263 509 entry 100 50 grey70 black;
+#X obj 262 464 symbol;
+#X obj 210 559 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/cursors.htm
+;
+#X msg 260 429 boat;
+#X msg 263 485 option cursor \$1;
+#X msg 220 429 clock;
+#X msg 356 429 dot;
+#X msg 386 429 dotbox;
+#X msg 433 429 gumby;
+#X msg 476 429 gobbler;
+#X msg 477 498 pirate;
+#X msg 477 455 mouse;
+#X msg 477 477 target;
+#X msg 438 227 option insertwidth \$1;
+#X obj 385 82 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 10 -262144
+-1 -1 0 1;
+#X msg 382 102 option borderwidth \$1;
+#X msg 456 269 scrollbar \$1;
+#X obj 456 249 tgl 15 0 empty empty empty 0 -6 0 10 -262144 -1 -1 0
+1;
+#X obj 566 417 keyup;
+#X msg 566 456 key \$1;
+#X floatatom 583 438 5 0 0 0 - - -;
+#X msg 269 210 key 3322;
+#X obj 566 492 entry 166 54 grey70 black;
+#X text 561 393 type single chars:;
+#X msg 656 442 key a;
+#X msg 657 464 key 9;
+#X obj 500 559 pddp/pddplink http://tcl.tk/man/tcl8.4/TkCmd/cursors.htm
+;
+#X text 367 538 for more cursors:;
+#X text 551 544 for more keynums:;
+#X msg 648 423 key 65228;
+#X msg 477 519 pencil;
+#X msg 295 429 coffee_mug;
+#X msg 700 464 key 32;
+#X connect 0 0 2 0;
+#X connect 0 0 10 0;
+#X connect 0 1 9 0;
+#X connect 0 1 13 0;
+#X connect 1 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 0;
+#X connect 9 0 11 0;
+#X connect 11 0 12 0;
+#X connect 11 1 0 0;
+#X connect 12 0 0 0;
+#X connect 15 0 7 0;
+#X connect 16 0 0 0;
+#X connect 17 0 0 0;
+#X connect 19 0 0 0;
+#X connect 20 0 0 0;
+#X connect 21 0 7 0;
+#X connect 22 0 21 0;
+#X connect 23 0 21 0;
+#X connect 24 0 21 0;
+#X connect 27 0 26 0;
+#X connect 28 0 27 0;
+#X connect 29 0 28 0;
+#X connect 30 0 28 0;
+#X connect 31 0 28 0;
+#X connect 32 0 28 0;
+#X connect 33 0 28 0;
+#X connect 34 0 28 0;
+#X connect 35 0 38 0;
+#X connect 36 0 35 0;
+#X connect 37 0 35 0;
+#X connect 38 0 41 0;
+#X connect 39 0 7 0;
+#X connect 42 0 56 0;
+#X connect 44 0 47 0;
+#X connect 46 0 44 0;
+#X connect 47 0 43 0;
+#X connect 48 0 44 0;
+#X connect 49 0 44 0;
+#X connect 50 0 44 0;
+#X connect 51 0 44 0;
+#X connect 52 0 44 0;
+#X connect 53 0 44 0;
+#X connect 54 0 44 0;
+#X connect 55 0 44 0;
+#X connect 56 0 41 0;
+#X connect 57 0 58 0;
+#X connect 58 0 26 0;
+#X connect 59 0 41 0;
+#X connect 60 0 59 0;
+#X connect 61 0 62 0;
+#X connect 61 0 63 0;
+#X connect 62 0 65 0;
+#X connect 64 0 0 0;
+#X connect 67 0 65 0;
+#X connect 68 0 65 0;
+#X connect 72 0 65 0;
+#X connect 73 0 44 0;
+#X connect 74 0 44 0;
+#X connect 75 0 65 0;
diff --git a/entry.c b/entry.c
new file mode 100644
index 0000000..dd96c6b
--- /dev/null
+++ b/entry.c
@@ -0,0 +1,848 @@
+
+/* text entry widget for PD *
+ * Based on button from GGEE by Guenter Geiger *
+ * Copyright Ben Bogart 2004 ben@ekran.org *
+
+ * This program is distributed under the terms of the GNU General Public *
+ * License *
+
+ * entry is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+
+ * entry is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. */
+
+#include <m_pd.h>
+#include <g_canvas.h>
+#include <stdio.h>
+#include <string.h>
+
+/* TODO: get Ctrl-A working to select all */
+/* TODO: set message doesnt work with a loadbang */
+
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#ifndef IOWIDTH
+#define IOWIDTH 4
+#endif
+
+#define DEFAULT_COLOR "grey70"
+
+#define TKW_HANDLE_HEIGHT 15
+#define TKW_HANDLE_WIDTH 15
+
+#define TKW_HANDLE_INSET -2
+#define ENTRY_DEFAULT_WIDTH 130
+#define ENTRY_DEFAULT_HEIGHT 130
+#define ENTRY_MIN_WIDTH 66
+#define ENTRY_MIN_HEIGHT 34
+
+#define TOTAL_INLETS 1
+#define TOTAL_OUTLETS 2
+
+#define DEBUG(x)
+//#define DEBUG(x) x
+
+typedef struct _entry
+{
+ t_object x_obj;
+ t_canvas *x_canvas;
+ t_glist *x_glist;
+
+ t_symbol *x_receive_name;
+
+ int x_height;
+ int x_width;
+ int x_resizing;
+
+ t_symbol *x_bgcolour;
+ t_symbol *x_fgcolour;
+
+ t_symbol *x_font_face;
+ t_int x_font_size;
+ t_symbol *x_font_weight;
+
+ t_float x_border;
+ t_symbol *x_relief;
+ t_int x_have_scrollbar;
+ t_int x_selected;
+
+ /* IDs for Tk widgets */
+ char *tcl_namespace;
+ char *canvas_id;
+ char *frame_id;
+ char *text_id;
+ char *scrollbar_id;
+ char *handle_id;
+ char *window_tag;
+ char *all_tag;
+
+ t_outlet* x_data_outlet;
+ t_outlet* x_status_outlet;
+} t_entry;
+
+
+static t_class *entry_class;
+
+
+static t_symbol *backspace_symbol;
+static t_symbol *return_symbol;
+static t_symbol *space_symbol;
+static t_symbol *tab_symbol;
+static t_symbol *escape_symbol;
+static t_symbol *left_symbol;
+static t_symbol *right_symbol;
+static t_symbol *up_symbol;
+static t_symbol *down_symbol;
+
+/* function prototypes */
+
+static void entry_getrect(t_gobj *z, t_glist *owner, int *xp1, int *yp1, int *xp2, int *yp2);
+static void entry_displace(t_gobj *z, t_glist *glist, int dx, int dy);
+static void entry_select(t_gobj *z, t_glist *glist, int state);
+static void entry_activate(t_gobj *z, t_glist *glist, int state);
+static void entry_delete(t_gobj *z, t_glist *glist);
+static void entry_vis(t_gobj *z, t_glist *glist, int vis);
+//static int entry_click(t_gobj *z, t_glist *glist, int xpix, int ypix, int shift, int alt, int dbl, int doit);
+static void entry_save(t_gobj *z, t_binbuf *b);
+
+
+static t_widgetbehavior entry_widgetbehavior = {
+w_getrectfn: entry_getrect,
+w_displacefn: entry_displace,
+w_selectfn: entry_select,
+w_activatefn: entry_activate,
+w_deletefn: entry_delete,
+w_visfn: entry_vis,
+w_clickfn: NULL,
+};
+
+/* widget helper functions */
+static void set_tk_widget_ids(t_entry *x, t_canvas *canvas)
+{
+ char buf[MAXPDSTRING];
+
+ x->x_canvas = canvas;
+
+ /* Tk ID for the current canvas that this object is drawn in */
+ sprintf(buf,".x%lx.c", (long unsigned int) canvas);
+ x->canvas_id = getbytes(strlen(buf) + 1);
+ strcpy(x->canvas_id, buf);
+
+ /* Tk ID for the "frame" the other things are drawn in */
+ sprintf(buf,"%s.frame%lx", x->canvas_id, (long unsigned int)x);
+ x->frame_id = getbytes(strlen(buf) + 1);
+ strcpy(x->frame_id, buf);
+
+ sprintf(buf,"%s.text%lx", x->frame_id, (long unsigned int)x);
+ x->text_id = getbytes(strlen(buf) + 1);
+ strcpy(x->text_id, buf); /* Tk ID for the "text", the meat! */
+
+ sprintf(buf,"%s.window%lx", x->canvas_id, (long unsigned int)x);
+ x->window_tag = getbytes(strlen(buf) + 1);
+ strcpy(x->window_tag, buf); /* Tk ID for the resizing "window" */
+
+ sprintf(buf,"%s.handle%lx", x->canvas_id, (long unsigned int)x);
+ x->handle_id = getbytes(strlen(buf) + 1);
+ strcpy(x->handle_id, buf); /* Tk ID for the resizing "handle" */
+
+ sprintf(buf,"%s.scrollbar%lx", x->frame_id, (long unsigned int)x);
+ x->scrollbar_id = getbytes(strlen(buf) + 1);
+ strcpy(x->scrollbar_id, buf); /* Tk ID for the optional "scrollbar" */
+
+ sprintf(buf,"all%lx", (long unsigned int)x);
+ x->all_tag = getbytes(strlen(buf) + 1);
+ strcpy(x->all_tag, buf); /* Tk ID for the optional "scrollbar" */
+}
+
+static int calculate_onset(t_entry *x, t_glist *glist,
+ int current_iolet, int total_iolets)
+{
+ DEBUG(post("calculate_onset"););
+ return(text_xpix(&x->x_obj, glist) + (x->x_width - IOWIDTH) \
+ * current_iolet / (total_iolets == 1 ? 1 : total_iolets - 1));
+}
+
+static void draw_inlets(t_entry *x, t_glist *glist, int firsttime,
+ int total_inlets, int total_outlets)
+{
+ DEBUG(post("draw_inlets in: %d out: %d", total_inlets, total_outlets););
+
+ int i, onset;
+
+ /* inlets */
+ for (i = 0; i < total_inlets; i++)
+ {
+ onset = calculate_onset(x, glist, i, total_inlets);
+ if (firsttime)
+ {
+ sys_vgui("%s create rectangle %d %d %d %d -tags {%xi%d %xi %s}\n",
+ x->canvas_id, onset, text_ypix(&x->x_obj, glist) - 2,
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist),
+ x, i, x, x->all_tag);
+ }
+ }
+ for (i = 0; i < total_outlets; i++) /* outlets */
+ {
+ onset = calculate_onset(x, glist, i, total_outlets);
+ if (firsttime)
+ {
+ sys_vgui("%s create rectangle %d %d %d %d -tags {%xo%d %xo %s}\n",
+ x->canvas_id, onset, text_ypix(&x->x_obj, glist) + x->x_height,
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_height + 2,
+ x, i, x, x->all_tag);
+ }
+ }
+ DEBUG(post("draw inlet end"););
+}
+
+static void erase_inlets(t_entry *x)
+{
+ DEBUG(post("erase_inlets"););
+/* Added tag for all inlets/outlets of one instance */
+ sys_vgui("%s delete %xi\n", x->canvas_id, x);
+ sys_vgui("%s delete %xo\n", x->canvas_id, x);
+
+}
+
+static void draw_scrollbar(t_entry *x)
+{
+ sys_vgui("pack %s -side right -fill y -before %s \n",
+ x->scrollbar_id, x->text_id);
+ x->x_have_scrollbar = 1;
+}
+
+static void erase_scrollbar(t_entry *x)
+{
+ sys_vgui("pack forget %s \n", x->scrollbar_id);
+ x->x_have_scrollbar = 0;
+}
+
+static void bind_button_events(t_entry *x)
+{
+ /* mouse buttons */
+ sys_vgui("bind %s <Button> {pdtk_canvas_mouse %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b 0}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ sys_vgui("bind %s <ButtonRelease> {pdtk_canvas_mouseup %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ sys_vgui("bind %s <Shift-Button> {pdtk_canvas_mouse %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b 1}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ sys_vgui("bind %s <Button-2> {pdtk_canvas_rightclick %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ sys_vgui("bind %s <Button-3> {pdtk_canvas_rightclick %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ sys_vgui("bind %s <$::modifier-Button> {pdtk_canvas_rightclick %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] %%b}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+ /* mouse motion */
+ sys_vgui("bind %s <Motion> {pdtk_canvas_motion %s \
+[expr %%X - [winfo rootx %s]] [expr %%Y - [winfo rooty %s]] 0}\n",
+ x->text_id, x->canvas_id, x->canvas_id, x->canvas_id);
+}
+
+static void create_widget(t_entry *x)
+{
+ DEBUG(post("create_widget"););
+ /* I guess this is for fine-tuning of the rect size based on width and height? */
+
+ sys_vgui("namespace eval entry%lx {} \n", x);
+
+ /* Seems we have to delete the widget in case it already exists (Provided by Guenter)*/
+ sys_vgui("destroy %s\n", x->frame_id);
+ sys_vgui("frame %s \n", x->frame_id);
+ sys_vgui("text %s -font {%s %d %s} -border 1 \
+ -highlightthickness 1 -relief sunken -bg \"%s\" -fg \"%s\" \
+ -yscrollcommand {%s set} \n",
+ x->text_id,
+ x->x_font_face->s_name, x->x_font_size, x->x_font_weight->s_name,
+ x->x_bgcolour->s_name, x->x_fgcolour->s_name,
+ x->scrollbar_id);
+ sys_vgui("scrollbar %s -command {%s yview}\n",
+ x->scrollbar_id, x->text_id);
+ sys_vgui("pack %s -side left -fill both -expand 1 \n", x->text_id);
+ sys_vgui("pack %s -side bottom -fill both -expand 1 \n", x->frame_id);
+
+ bind_button_events(x);
+ sys_vgui("bind %s <KeyRelease> {+pdsend {%s keyup %%N}} \n",
+ x->text_id, x->x_receive_name->s_name);
+}
+
+static void entry_drawme(t_entry *x, t_glist *glist, int firsttime)
+{
+ DEBUG(post("entry_drawme: firsttime %d canvas %lx glist %lx", firsttime, x->x_canvas, glist););
+ set_tk_widget_ids(x,glist_getcanvas(glist));
+ if (firsttime)
+ {
+ create_widget(x);
+ draw_inlets(x, glist, firsttime, TOTAL_INLETS, TOTAL_OUTLETS);
+ if(x->x_have_scrollbar) draw_scrollbar(x);
+ sys_vgui("%s create window %d %d -anchor nw -window %s \
+ -tags {%s %s} -width %d -height %d \n", x->canvas_id,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),
+ x->frame_id, x->window_tag, x->all_tag, x->x_width, x->x_height);
+ }
+ else
+ {
+ post("NO MORE COORDS");
+// sys_vgui("%s coords %s %d %d\n", x->canvas_id, x->all_tag,
+// text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));
+ }
+}
+
+
+static void entry_erase(t_entry* x,t_glist* glist)
+{
+ DEBUG(post("entry_erase: canvas %lx glist %lx", x->x_canvas, glist););
+
+ set_tk_widget_ids(x,glist_getcanvas(glist));
+ erase_inlets(x);
+ sys_vgui("destroy %s\n", x->frame_id);
+ sys_vgui("%s delete %s\n", x->canvas_id, x->all_tag);
+}
+
+
+
+/* ------------------------ text widgetbehaviour----------------------------- */
+
+
+static void entry_getrect(t_gobj *z, t_glist *owner,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+// DEBUG(post("entry_getrect");); /* this one is very chatty :D */
+ t_entry *x = (t_entry*)z;
+ *xp1 = text_xpix(&x->x_obj, owner);
+ *yp1 = text_ypix(&x->x_obj, owner);
+ *xp2 = *xp1 + x->x_width;
+ *yp2 = *yp1 + x->x_height + 2; // add 2 to give space for outlets
+}
+
+static void entry_displace(t_gobj *z, t_glist *glist, int dx, int dy)
+{
+ t_entry *x = (t_entry *)z;
+ DEBUG(post("entry_displace: canvas %lx glist %lx", x->x_canvas, glist););
+ x->x_obj.te_xpix += dx;
+ x->x_obj.te_ypix += dy;
+ if (glist_isvisible(glist))
+ {
+ set_tk_widget_ids(x,glist_getcanvas(glist));
+ sys_vgui("%s move %s %d %d\n", x->canvas_id, x->all_tag, dx, dy);
+ sys_vgui("%s move RSZ %d %d\n", x->canvas_id, dx, dy);
+/* sys_vgui("%s coords %s %d %d %d %d\n", x->canvas_id, x->all_tag,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1,
+ text_xpix(&x->x_obj, glist) + x->x_width,
+ text_ypix(&x->x_obj, glist) + x->x_height-2);*/
+// entry_drawme(x, glist, 0);
+ canvas_fixlinesfor(glist, (t_text*) x);
+ }
+ DEBUG(post("displace end"););
+}
+
+static void entry_select(t_gobj *z, t_glist *glist, int state)
+{
+ t_entry *x = (t_entry *)z;
+ DEBUG(post("entry_select: canvas %lx glist %lx state %d", x->x_canvas, glist, state););
+
+ if( (state) && (!x->x_selected))
+ {
+ sys_vgui("%s configure -bg #bdbddd -state disabled -cursor $cursor_editmode_nothing\n",
+ x->text_id);
+ x->x_selected = 1;
+ }
+ else if (!state)
+ {
+ sys_vgui("%s configure -bg grey -state normal -cursor xterm\n",
+ x->text_id);
+ /* activatefn never gets called with 0, so destroy here */
+ sys_vgui("destroy %s\n", x->handle_id);
+ x->x_selected = 0;
+ }
+}
+
+static void entry_activate(t_gobj *z, t_glist *glist, int state)
+{
+ DEBUG(post("entry_activate"););
+ t_entry *x = (t_entry *)z;
+ int x1, y1, x2, y2;
+
+ if(state)
+ {
+ entry_getrect(z, glist, &x1, &y1, &x2, &y2);
+ sys_vgui("canvas %s -width %d -height %d -bg #ddd -bd 0 \
+-highlightthickness 3 -highlightcolor {#f00} -cursor bottom_right_corner\n",
+ x->handle_id, TKW_HANDLE_WIDTH, TKW_HANDLE_HEIGHT);
+ int handle_x1 = x2 - TKW_HANDLE_WIDTH;
+ int handle_y1 = y2 - (TKW_HANDLE_HEIGHT - TKW_HANDLE_INSET);
+// int handle_x2 = x2;
+// int handle_y2 = y2 - TKW_HANDLE_INSET;
+/* no worky, this should draw MAC OS X style lines on the resize handle */
+/* sys_vgui("%s create line %d %d %d %d -fill black -tags RESIZE_LINES\n", */
+/* x->handle_id, handle_x2, handle_y1, handle_x1, handle_y2); */
+ sys_vgui("%s create window %d %d -anchor nw -width %d -height %d -window %s -tags RSZ\n",
+ x->canvas_id, handle_x1, handle_y1,
+ TKW_HANDLE_WIDTH, TKW_HANDLE_HEIGHT,
+ x->handle_id, x->all_tag);
+ sys_vgui("raise %s\n", x->handle_id);
+ sys_vgui("bind %s <Button> {pdsend {%s resize_click 1}}\n",
+ x->handle_id, x->x_receive_name->s_name);
+ sys_vgui("bind %s <ButtonRelease> {pdsend {%s resize_click 0}}\n",
+ x->handle_id, x->x_receive_name->s_name);
+ sys_vgui("bind %s <Motion> {pdsend {%s resize_motion %%x %%y }}\n",
+ x->handle_id, x->x_receive_name->s_name);
+ }
+}
+
+static void entry_delete(t_gobj *z, t_glist *glist)
+{
+ DEBUG(post("entry_delete: glist %lx", glist););
+ t_text *x = (t_text *)z;
+ canvas_deletelinesfor(glist, x);
+}
+
+
+static void entry_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_entry *x = (t_entry*)z;
+ DEBUG(post("entry_vis: vis %d canvas %lx glist %lx", vis, x->x_canvas, glist););
+ if (vis) {
+ entry_drawme(x, glist, 1);
+ }
+ else {
+ entry_erase(x, glist);
+ }
+}
+
+/* the clickfn is only called in run mode
+static int entry_click(t_gobj *z, t_glist *glist, int xpix, int ypix,
+ int shift, int alt, int dbl, int doit)
+{
+ t_entry *x = (t_entry *)z;
+ DEBUG(post("entry_click x:%d y:%d edit: %d", xpix, ypix, x->x_canvas->gl_edit););
+ return 0;
+}
+*/
+
+static void entry_append(t_entry* x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("entry_append"););
+ int i;
+ t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */
+ t_float tmp_float;
+
+ for(i=0; i<argc ; i++)
+ {
+ tmp_symbol = atom_getsymbolarg(i, argc, argv);
+ if(tmp_symbol == &s_)
+ {
+ tmp_float = atom_getfloatarg(i, argc , argv);
+ sys_vgui("lappend ::%s::list %g \n", x->tcl_namespace, tmp_float );
+ }
+ else
+ {
+ sys_vgui("lappend ::%s::list %s \n", x->tcl_namespace, tmp_symbol->s_name );
+ }
+ }
+ sys_vgui("append ::%s::list \" \"\n", x->tcl_namespace);
+ sys_vgui("%s insert end $::%s::list ; unset ::%s::list \n",
+ x->text_id, x->tcl_namespace, x->tcl_namespace );
+ sys_vgui("%s yview end-2char \n", x->text_id );
+}
+
+static void entry_key(t_entry* x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("entry_key"););
+ t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */
+ t_int tmp_int;
+
+ tmp_symbol = atom_getsymbolarg(0, argc, argv);
+ if(tmp_symbol == &s_)
+ {
+ tmp_int = (t_int) atom_getfloatarg(0, argc , argv);
+ if(tmp_int < 10)
+ {
+ sys_vgui("%s insert end %d\n", x->text_id, tmp_int);
+ }
+ else if(tmp_int == 10)
+ {
+ sys_vgui("%s insert end {\n}\n", x->text_id);
+ }
+ else
+ {
+ sys_vgui("%s insert end [format \"%c\" %d]\n", x->text_id, tmp_int);
+ }
+ }
+ else
+ {
+ sys_vgui("%s insert end %s\n", x->text_id, tmp_symbol->s_name );
+ }
+ sys_vgui("%s yview end-2char \n", x->text_id );
+}
+
+/* Clear the contents of the text widget */
+static void entry_clear(t_entry* x)
+{
+ sys_vgui("%s delete 0.0 end \n", x->text_id);
+}
+
+/* Function to reset the contents of the entry box */
+static void entry_set(t_entry* x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("entry_set"););
+
+ entry_clear(x);
+ entry_append(x, s, argc, argv);
+}
+
+static void entry_output(t_entry* x, t_symbol *s, int argc, t_atom *argv)
+{
+ outlet_list(x->x_data_outlet, s, argc, argv );
+}
+
+/* Pass the contents of the text widget onto the entry_output fuction above */
+static void entry_bang_output(t_entry* x)
+{
+ /* With "," and ";" escaping thanks to JMZ */
+ sys_vgui("pdsend \"%s output [string map {\",\" \"\\\\,\" \";\" \"\\\\;\"} \
+ [%s get 0.0 end]] \"\n",
+ x->x_receive_name->s_name, x->text_id);
+}
+
+static void entry_keyup(t_entry *x, t_float f)
+{
+/* DEBUG(post("entry_keyup");); */
+ int keycode = (int) f;
+ char buf[10];
+ t_symbol *output_symbol;
+
+ if( (keycode > 32 ) && (keycode < 65288) )
+ {
+ snprintf(buf, 2, "%c", keycode);
+ output_symbol = gensym(buf);
+ } else
+ switch(keycode)
+ {
+ case 32: /* space */
+ output_symbol = space_symbol;
+ break;
+ case 65293: /* return */
+ output_symbol = return_symbol;
+ break;
+ case 65288: /* backspace */
+ output_symbol = backspace_symbol;
+ break;
+ case 65289: /* tab */
+ output_symbol = tab_symbol;
+ break;
+ case 65307: /* escape */
+ output_symbol = escape_symbol;
+ break;
+ case 65361: /* left */
+ output_symbol = left_symbol;
+ break;
+ case 65363: /* right */
+ output_symbol = right_symbol;
+ break;
+ case 65362: /* up */
+ output_symbol = up_symbol;
+ break;
+ case 65364: /* down */
+ output_symbol = down_symbol;
+ break;
+ default:
+ snprintf(buf, 10, "key_%d", keycode);
+ DEBUG(post("keyup: %d", keycode););
+ output_symbol = gensym(buf);
+ }
+ outlet_symbol(x->x_status_outlet, output_symbol);
+}
+
+static void entry_save(t_gobj *z, t_binbuf *b)
+{
+ t_entry *x = (t_entry *)z;
+
+ binbuf_addv(b, "ssiisiiss;", &s__X, gensym("obj"),
+ x->x_obj.te_xpix, x->x_obj.te_ypix,
+ atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)),
+ x->x_width, x->x_height, x->x_bgcolour, x->x_fgcolour);
+}
+
+
+static void entry_option_float(t_entry* x, t_symbol *option, t_float value)
+{
+ sys_vgui("%s configure -%s %f \n",
+ x->text_id, option->s_name, value);
+}
+
+static void entry_option_symbol(t_entry* x, t_symbol *option, t_symbol *value)
+{
+ sys_vgui("%s configure -%s {%s} \n",
+ x->text_id, option->s_name, value->s_name);
+}
+
+static void entry_option(t_entry *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_symbol *tmp_symbol = s; /* <-- this gets rid of the unused variable warning */
+
+ tmp_symbol = atom_getsymbolarg(1, argc, argv);
+ if(tmp_symbol == &s_)
+ {
+ entry_option_float(x,atom_getsymbolarg(0, argc, argv),
+ atom_getfloatarg(1, argc, argv));
+ }
+ else
+ {
+ entry_option_symbol(x,atom_getsymbolarg(0, argc, argv),tmp_symbol);
+ }
+}
+
+static void entry_scrollbar(t_entry *x, t_float f)
+{
+ if(f > 0)
+ draw_scrollbar(x);
+ else
+ erase_scrollbar(x);
+}
+
+
+/* function to change colour of text background */
+void entry_bgcolour(t_entry* x, t_symbol* bgcol)
+{
+ x->x_bgcolour = bgcol;
+ sys_vgui("%s configure -background \"%s\" \n",
+ x->text_id, x->x_bgcolour->s_name);
+}
+
+/* function to change colour of text foreground */
+void entry_fgcolour(t_entry* x, t_symbol* fgcol)
+{
+ x->x_fgcolour = fgcol;
+ sys_vgui("%s configure -foreground \"%s\" \n",
+ x->text_id, x->x_fgcolour->s_name);
+}
+
+static void entry_fontsize(t_entry *x, t_float font_size)
+{
+ DEBUG(post("entry_fontsize"););
+ if(font_size > 8)
+ {
+ x->x_font_size = (t_int)font_size;
+ sys_vgui("%s configure -font {%s %d %s} \n",
+ x->text_id,
+ x->x_font_face->s_name, x->x_font_size,
+ x->x_font_weight->s_name);
+ }
+ else
+ pd_error(x,"entry: invalid font size: %f",font_size);
+}
+
+static void entry_size(t_entry *x, t_float width, t_float height)
+{
+ DEBUG(post("entry_size"););
+ x->x_height = height;
+ x->x_width = width;
+ if(glist_isvisible(x->x_glist))
+ {
+ sys_vgui("%s itemconfigure %s -width %d -height %d\n",
+ x->canvas_id, x->window_tag, x->x_width, x->x_height);
+ canvas_fixlinesfor(x->x_glist, (t_text *)x); // 2nd inlet
+ }
+}
+
+/* callback functions */
+static void entry_click_callback(t_entry *x, t_floatarg f)
+{
+ if( (x->x_glist->gl_edit) && (x->x_glist == x->x_canvas) )
+ {
+ entry_select((t_gobj *)x, x->x_glist, f);
+ }
+}
+
+static void entry_resize_click_callback(t_entry *x, t_floatarg f)
+{
+ t_canvas *canvas = (glist_isvisible(x->x_glist) ? x->x_canvas : 0);
+ int newstate = (int)f;
+ if (x->x_resizing && newstate == 0)
+ {
+ if (canvas)
+ {
+ draw_inlets(x, canvas, 1, TOTAL_INLETS, TOTAL_OUTLETS);
+ canvas_fixlinesfor(x->x_glist, (t_text *)x); // 2nd inlet
+ }
+ }
+ else if (!x->x_resizing && newstate)
+ {
+ erase_inlets(x);
+ }
+ x->x_resizing = newstate;
+}
+
+static void entry_resize_motion_callback(t_entry *x, t_floatarg f1, t_floatarg f2)
+{
+ DEBUG(post("entry_resize_motion_callback"););
+ if (x->x_resizing)
+ {
+ int dx = (int)f1, dy = (int)f2;
+ if (glist_isvisible(x->x_glist))
+ {
+ x->x_width += dx;
+ x->x_height += dy;
+ sys_vgui("%s itemconfigure %s -width %d -height %d\n",
+ x->canvas_id, x->window_tag,
+ x->x_width, x->x_height);
+ sys_vgui("%s move RSZ %d %d\n",
+ x->canvas_id, dx, dy);
+ }
+ }
+}
+
+static void entry_free(t_entry *x)
+{
+ pd_unbind(&x->x_obj.ob_pd, x->x_receive_name);
+}
+
+static void *entry_new(t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("entry_new"););
+ t_entry *x = (t_entry *)pd_new(entry_class);
+ char buf[MAXPDSTRING];
+
+ x->x_height = 1;
+ x->x_font_face = gensym("helvetica");
+ x->x_font_size = 10;
+ x->x_font_weight = gensym("normal");
+ x->x_have_scrollbar = 0;
+ x->x_selected = 0;
+
+ if (argc < 4)
+ {
+ post("entry: You must enter at least 4 arguments. Default values used.");
+ x->x_width = ENTRY_DEFAULT_WIDTH;
+ x->x_height = ENTRY_DEFAULT_HEIGHT;
+ x->x_bgcolour = gensym(DEFAULT_COLOR);
+ x->x_fgcolour = gensym("black");
+
+ } else {
+ /* Copy args into structure */
+ x->x_width = atom_getint(argv);
+ x->x_height = atom_getint(argv+1);
+ x->x_bgcolour = atom_getsymbol(argv+2);
+ x->x_fgcolour = atom_getsymbol(argv+3);
+ }
+
+ x->x_data_outlet = outlet_new(&x->x_obj, &s_float);
+ x->x_status_outlet = outlet_new(&x->x_obj, &s_symbol);
+
+ sprintf(buf,"entry%lx",(long unsigned int)x);
+ x->tcl_namespace = getbytes(strlen(buf) + 1);
+ strcpy(x->tcl_namespace, buf);
+
+ sprintf(buf,"#%s", x->tcl_namespace);
+ x->x_receive_name = gensym(buf);
+ pd_bind(&x->x_obj.ob_pd, x->x_receive_name);
+
+ x->x_glist = canvas_getcurrent();
+ set_tk_widget_ids(x, x->x_glist);
+
+ return (x);
+}
+
+void entry_setup(void) {
+ entry_class = class_new(gensym("entry"), (t_newmethod)entry_new,
+ (t_method)entry_free, sizeof(t_entry),0,A_GIMME,0);
+
+ class_addbang(entry_class, (t_method)entry_bang_output);
+
+ class_addmethod(entry_class, (t_method)entry_keyup,
+ gensym("keyup"),
+ A_DEFFLOAT,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_scrollbar,
+ gensym("scrollbar"),
+ A_DEFFLOAT,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_option,
+ gensym("option"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_size,
+ gensym("size"),
+ A_DEFFLOAT,
+ A_DEFFLOAT,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_fontsize,
+ gensym("fontsize"),
+ A_DEFFLOAT,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_output,
+ gensym("output"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_set,
+ gensym("set"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_append,
+ gensym("append"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_key,
+ gensym("key"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_clear,
+ gensym("clear"),
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_bgcolour,
+ gensym("bgcolour"),
+ A_DEFSYMBOL,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_fgcolour,
+ gensym("fgcolour"),
+ A_DEFSYMBOL,
+ 0);
+
+ class_addmethod(entry_class, (t_method)entry_click_callback,
+ gensym("click"), A_FLOAT, 0);
+ class_addmethod(entry_class, (t_method)entry_resize_click_callback,
+ gensym("resize_click"), A_FLOAT, 0);
+ class_addmethod(entry_class, (t_method)entry_resize_motion_callback,
+ gensym("resize_motion"), A_FLOAT, A_FLOAT, 0);
+
+ class_setwidget(entry_class,&entry_widgetbehavior);
+ class_setsavefn(entry_class,&entry_save);
+
+ backspace_symbol = gensym("backspace");
+ return_symbol = gensym("return");
+ space_symbol = gensym("space");
+ tab_symbol = gensym("tab");
+ escape_symbol = gensym("escape");
+ left_symbol = gensym("left");
+ right_symbol = gensym("right");
+ up_symbol = gensym("up");
+ down_symbol = gensym("down");
+}
+
+
diff --git a/examples/clock.pd b/examples/clock.pd
new file mode 100644
index 0000000..601a29b
--- /dev/null
+++ b/examples/clock.pd
@@ -0,0 +1,38 @@
+#N canvas 499 272 303 143 10;
+#X obj 27 42 knob 20 20 0 660 0 0 *nil* *hour* empty 0 -8 192 8 -1109
+-1109 -42246 891 1;
+#X obj 17 32 knob 40 40 0 55 0 0 *nil* *minute* empty 0 -8 192 8 -258699
+-258699 -42246 168 1;
+#N canvas 0 0 337 294 gettime 0;
+#X msg 63 92 bang;
+#X obj 63 118 time;
+#X obj 50 40 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1
+;
+#X floatatom 13 157 5 0 0;
+#X floatatom 77 157 5 0 0;
+#X floatatom 122 157 5 0 0;
+#X obj 35 258 s *hour*;
+#X obj 77 211 s *minute*;
+#X obj 77 181 expr ($f1 + 28) % 60 + 0.37;
+#X obj 51 63 metro 60000;
+#X obj 50 17 loadbang;
+#X obj 33 212 f;
+#X obj 33 181 t b f;
+#X obj 35 235 expr (($f1 * 60) + $f2 + 335) % 720 + 0.37;
+#X connect 0 0 1 0;
+#X connect 1 0 3 0;
+#X connect 1 1 4 0;
+#X connect 1 2 5 0;
+#X connect 2 0 9 0;
+#X connect 3 0 11 0;
+#X connect 4 0 8 0;
+#X connect 4 0 12 0;
+#X connect 8 0 7 0;
+#X connect 9 0 0 0;
+#X connect 10 0 2 0;
+#X connect 11 0 13 0;
+#X connect 12 0 11 0;
+#X connect 12 1 13 1;
+#X connect 13 0 6 0;
+#X restore 5 6 pd gettime;
+#X text 122 51 written by Orm Finnendahl;
diff --git a/flatgui-meta.pd b/flatgui-meta.pd
new file mode 100644
index 0000000..d8add7e
--- /dev/null
+++ b/flatgui-meta.pd
@@ -0,0 +1,7 @@
+#N canvas 15 49 200 200 10;
+#N canvas 25 49 420 300 META 1;
+#X text 13 41 NAME flatgui;
+#X text 10 25 AUTHOR Ben Bogart, Christoph Kummerer, Frank Barknect, Guenther Geiger, Hans-Christoph Steiner, Krzystof Czaja, Miller Puckette, Olaf Matthes, Thomas Musil;
+#X text 10 10 VERSION 0.1;
+#X text 10 100 LICENSE GPLv3;
+#X restore 10 10 pd META;
diff --git a/knob-help.pd b/knob-help.pd
new file mode 100644
index 0000000..a9f1f85
--- /dev/null
+++ b/knob-help.pd
@@ -0,0 +1,15 @@
+#N canvas 380 59 361 316 10;
+#X obj 142 44 knob 20 20 0 127 0 0 knob knob knob 0 -8 192 8 -143491
+-260818 -1 0 1;
+#X obj 90 121 knob 128 128 100 -100 0 1 knob knob empty 0 -8 192 8
+-262144 -258699 -1 4300 0;
+#X obj 129 269 nbx 5 14 -1e+37 1e+37 0 0 knob knob empty 0 -6 192 10
+-262144 -1 -1 0 256;
+#X obj 136 75 knob 32 32 0 127 0 0 knob knob empty 0 -8 192 8 -262144
+-24198 -1 0 1;
+#X obj 271 162 knob 32 32 0 127 0 0 empty empty empty 0 -8 0 8 -262144
+-250685 -62784 2 1;
+#X floatatom 271 207 8 0 0;
+#X floatatom 271 135 5 0 0;
+#X connect 4 0 5 0;
+#X connect 6 0 4 0;
diff --git a/knob.c b/knob.c
new file mode 100644
index 0000000..ca4fcda
--- /dev/null
+++ b/knob.c
@@ -0,0 +1,793 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */
+/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */
+
+/* 'knob' gui object by Frank Barknecht, 'externalised' by Olaf Matthes */
+/* changed for devel_0.37 by Christoph Kummerer - hardly tested */
+
+/* I had to out-comment the loadbang stuff because I couldn't find the code
+ in Pd where it is declared */
+
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "m_pd.h"
+
+#ifndef PD_MAJOR_VERSION
+#include "s_stuff.h"
+#else
+#include "m_imp.h"
+#endif
+
+#include "g_canvas.h"
+
+#include "g_all_guis.h"
+#include <math.h>
+
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+
+#ifndef M_PI
+#define M_PI 3.141592654
+#endif
+
+#define IEM_KNOB_DEFAULTSIZE 32
+
+/* ------------ knob gui-vertical slider ----------------------- */
+
+t_widgetbehavior knob_widgetbehavior;
+static t_class *knob_class;
+t_symbol *iemgui_key_sym=0; /* taken from g_all_guis.c */
+
+typedef struct _knob /* taken from Frank's modyfied g_all_guis.h */
+{
+ t_iemgui x_gui;
+ int x_pos;
+ int x_val;
+ int x_lin0_log1;
+ int x_steady;
+ double x_min;
+ double x_max;
+ double x_k;
+} t_knob;
+
+/* widget helper functions */
+
+static void knob_draw_update(t_knob *x, t_glist *glist)
+{
+ if (glist_isvisible(glist))
+ {
+ /* compute dial:*/
+ float radius = 0.5*(float)x->x_gui.x_h;
+ double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*( (double)x->x_val*0.01/(double)x->x_gui.x_h );
+ int start = -80;
+ int extent = 350 - (int)(360.0*angle/(2.0*M_PI));
+ /* center point: */
+ int x1 = text_xpix(&x->x_gui.x_obj, glist) + radius;
+ int y1 = text_ypix(&x->x_gui.x_obj, glist) + radius;
+ int x2 = text_xpix(&x->x_gui.x_obj, glist) + radius + radius * sin( -angle);
+ int y2 = text_ypix(&x->x_gui.x_obj, glist) + radius + radius * cos( angle);
+
+ sys_vgui(".x%lx.c coords %xKNOB %d %d %d %d\n",
+ glist_getcanvas(glist), x,
+ x1, /* x1 */
+ y1, /* y1 */
+ x2, /* x2 */
+ y2 /* y2 */
+ );
+
+ /* post("knob: (%d, %d) (%d, %d)", x1,y1,x2,y2); */
+
+ sys_vgui(".x%lx.c itemconfigure %xBASE -start %d -extent %d \n", glist_getcanvas(glist), x,
+ start, extent);
+ }
+}
+
+static void knob_draw_new(t_knob *x, t_glist *glist)
+{
+ int xpos=text_xpix(&x->x_gui.x_obj, glist);
+ int ypos=text_ypix(&x->x_gui.x_obj, glist);
+ /* int r = ypos + x->x_gui.x_h - (x->x_val + 50)/100; */
+ t_canvas *canvas=glist_getcanvas(glist);
+
+ /* compute dial:*/
+ float radius = 0.5*(float)x->x_gui.x_h;
+ /* center point: */
+ int x1 = xpos + radius;
+ int y1 = ypos + radius;
+ /* dial */
+ double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((float)x->x_val*0.01/(float)(x->x_gui.x_h));
+ int x2 = x1 + radius * sin(-angle);
+ int y2 = y1 + radius * cos(angle);
+
+
+ /* BASE2 */
+ sys_vgui(".x%lx.c create arc %d %d %d %d -outline #%6.6x -style arc -width 3 -start -80 -extent 340 -tags %xBASE2\n",
+ canvas,
+ xpos, ypos, /* upper left */
+ xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, /* lower right */
+ x->x_gui.x_fcol, x);
+
+ /* BASE */
+ sys_vgui(".x%lx.c create arc %d %d %d %d -fill #%6.6x -style arc -width 3 -start -80 -extent 340 -tags %xBASE\n",
+ canvas,
+ xpos, ypos, /* upper left */
+ xpos + x->x_gui.x_h, ypos + x->x_gui.x_h, /* lower right */
+ x->x_gui.x_bcol, x);
+ /* LINE */
+ sys_vgui(".x%lx.c create line %d %d %d %d -width 3 -fill #%6.6x -capstyle round -tags %xKNOB\n",
+ canvas,
+ x1, /* x1 */
+ y1, /* y1 */
+ x2, /* x2 */
+ y2, /* y2 */
+ x->x_gui.x_fcol, /* color */
+ x);
+
+ sys_vgui(".x%lx.c create text %d %d -text {%s} -anchor w \
+ -font {%s %d bold} -fill #%6.6x -tags %xLABEL\n",
+ canvas, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy,
+ strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"",
+ x->x_gui.x_font, x->x_gui.x_fontsize, x->x_gui.x_lcol, x);
+ if(!x->x_gui.x_fsf.x_snd_able)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xOUT%d\n",
+ canvas,
+ xpos, ypos + x->x_gui.x_h+2,
+ xpos+7, ypos + x->x_gui.x_h+3,
+ x, 0);
+ if(!x->x_gui.x_fsf.x_rcv_able)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xIN%d\n",
+ canvas,
+ xpos, ypos-2,
+ xpos+7, ypos-1,
+ x, 0);
+}
+
+static void knob_draw_move(t_knob *x, t_glist *glist)
+{
+ int xpos=text_xpix(&x->x_gui.x_obj, glist);
+ int ypos=text_ypix(&x->x_gui.x_obj, glist);
+ /* int r = ypos + x->x_gui.x_h - (x->x_val + 50)/100; */
+ t_canvas *canvas=glist_getcanvas(glist);
+ /* compute dial:*/
+ float radius = 0.5*(float)x->x_gui.x_h;
+ /* float angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*((float)x->x_val*0.01/(float)(x->x_gui.x_h)); */
+ double angle = 7.0/36.0 + 34.0/36.0*2.0*M_PI*( (double)x->x_val*0.01/(double)x->x_gui.x_h );
+ /* center point: */
+ int x1 = text_xpix(&x->x_gui.x_obj, glist) + radius;
+ int y1 = text_ypix(&x->x_gui.x_obj, glist) + radius;
+ int x2 = text_xpix(&x->x_gui.x_obj, glist) + radius + radius * sin( -angle);
+ int y2 = text_ypix(&x->x_gui.x_obj, glist) + radius + radius * cos( angle);
+
+
+
+ sys_vgui(".x%lx.c coords %xKNOB %d %d %d %d\n",
+ canvas, x,
+ x1, /* x1 */
+ y1, /* y1 */
+ x2, /* x2 */
+ y2 /* y2 */
+ );
+ /* post("knob: (%d, %d) (%d, %d)", x1,y1,x2,y2); */
+
+ sys_vgui(".x%lx.c coords %xBASE %d %d %d %d\n",
+ canvas, x,
+ xpos, ypos,
+ xpos + x->x_gui.x_h, ypos + x->x_gui.x_h);
+
+ sys_vgui(".x%lx.c coords %xBASE2 %d %d %d %d\n",
+ canvas, x,
+ xpos, ypos,
+ xpos + x->x_gui.x_h, ypos + x->x_gui.x_h);
+
+ sys_vgui(".x%lx.c coords %xLABEL %d %d\n",
+ canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy);
+ if(!x->x_gui.x_fsf.x_snd_able)
+ sys_vgui(".x%lx.c coords %xOUT%d %d %d %d %d\n",
+ canvas, x, 0,
+ xpos, ypos + x->x_gui.x_h+2,
+ xpos+7, ypos + x->x_gui.x_h+3);
+ if(!x->x_gui.x_fsf.x_rcv_able)
+ sys_vgui(".x%lx.c coords %xIN%d %d %d %d %d\n",
+ canvas, x, 0,
+ xpos, ypos-2,
+ xpos+7, ypos-1);
+}
+
+static void knob_draw_erase(t_knob* x,t_glist* glist)
+{
+ t_canvas *canvas=glist_getcanvas(glist);
+
+ sys_vgui(".x%lx.c delete %xBASE\n", canvas, x);
+ sys_vgui(".x%lx.c delete %xBASE2\n", canvas, x);
+ sys_vgui(".x%lx.c delete %xKNOB\n", canvas, x);
+ sys_vgui(".x%lx.c delete %xLABEL\n", canvas, x);
+ if(!x->x_gui.x_fsf.x_snd_able)
+ sys_vgui(".x%lx.c delete %xOUT%d\n", canvas, x, 0);
+ if(!x->x_gui.x_fsf.x_rcv_able)
+ sys_vgui(".x%lx.c delete %xIN%d\n", canvas, x, 0);
+}
+
+static void knob_draw_config(t_knob* x,t_glist* glist)
+{
+ t_canvas *canvas=glist_getcanvas(glist);
+
+ sys_vgui(".x%lx.c itemconfigure %xLABEL -font {%s %d bold} -fill #%6.6x -text {%s} \n",
+ canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize,
+ x->x_gui.x_fsf.x_selected?IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol,
+ strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"");
+ sys_vgui(".x%lx.c itemconfigure %xKNOB -fill #%6.6x\n", canvas,
+ x, x->x_gui.x_fcol);
+ sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas,
+ x, x->x_gui.x_fcol);
+ sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas,
+ x, x->x_gui.x_bcol);
+}
+
+static void knob_draw_io(t_knob* x,t_glist* glist, int old_snd_rcv_flags)
+{
+ int xpos=text_xpix(&x->x_gui.x_obj, glist);
+ int ypos=text_ypix(&x->x_gui.x_obj, glist);
+ t_canvas *canvas=glist_getcanvas(glist);
+
+ if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xOUT%d\n",
+ canvas,
+ xpos, ypos + x->x_gui.x_h+2,
+ xpos+7, ypos + x->x_gui.x_h+3,
+ x, 0);
+ if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able)
+ sys_vgui(".x%lx.c delete %xOUT%d\n", canvas, x, 0);
+ if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %xIN%d\n",
+ canvas,
+ xpos, ypos-2,
+ xpos+7, ypos-1,
+ x, 0);
+ if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able)
+ sys_vgui(".x%lx.c delete %xIN%d\n", canvas, x, 0);
+}
+
+static void knob_draw_select(t_knob *x, t_glist *glist)
+{
+ t_canvas *canvas=glist_getcanvas(glist);
+
+ if(x->x_gui.x_fsf.x_selected)
+ {
+ pd_bind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym);
+ sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
+ sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
+ sys_vgui(".x%lx.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED);
+ }
+ else
+ {
+ pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym);
+ sys_vgui(".x%lx.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL);
+ sys_vgui(".x%lx.c itemconfigure %xBASE2 -outline #%6.6x\n", canvas, x, x->x_gui.x_fcol);
+ sys_vgui(".x%lx.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol);
+ }
+}
+
+void knob_draw(t_knob *x, t_glist *glist, int mode)
+{
+ if(mode == IEM_GUI_DRAW_MODE_UPDATE)
+ knob_draw_update(x, glist);
+ else if(mode == IEM_GUI_DRAW_MODE_MOVE)
+ knob_draw_move(x, glist);
+ else if(mode == IEM_GUI_DRAW_MODE_NEW)
+ knob_draw_new(x, glist);
+ else if(mode == IEM_GUI_DRAW_MODE_SELECT)
+ knob_draw_select(x, glist);
+ else if(mode == IEM_GUI_DRAW_MODE_ERASE)
+ knob_draw_erase(x, glist);
+ else if(mode == IEM_GUI_DRAW_MODE_CONFIG)
+ knob_draw_config(x, glist);
+ else if(mode >= IEM_GUI_DRAW_MODE_IO)
+ knob_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);
+}
+
+/* ------------------------ knob widgetbehaviour----------------------------- */
+
+
+static void knob_getrect(t_gobj *z, t_glist *glist,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+ t_knob* x = (t_knob*)z;
+
+ *xp1 = text_xpix(&x->x_gui.x_obj, glist);
+ *yp1 = text_ypix(&x->x_gui.x_obj, glist) - 2;
+ *xp2 = *xp1 + x->x_gui.x_h;
+ *yp2 = *yp1 + x->x_gui.x_h + 5;
+}
+
+static void knob_save(t_gobj *z, t_binbuf *b)
+{
+ t_knob *x = (t_knob *)z;
+ int bflcol[3], *ip1, *ip2;
+ t_symbol *srl[3];
+
+ iemgui_save(&x->x_gui, srl, bflcol);
+ ip1 = (int *)(&x->x_gui.x_isa);
+ ip2 = (int *)(&x->x_gui.x_fsf);
+ binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", gensym("#X"),gensym("obj"),
+ (t_int)x->x_gui.x_obj.te_xpix, (t_int)x->x_gui.x_obj.te_ypix,
+ atom_getsymbol(binbuf_getvec(x->x_gui.x_obj.te_binbuf)),
+ x->x_gui.x_h, x->x_gui.x_h,
+ (float)x->x_min, (float)x->x_max,
+ x->x_lin0_log1, (*ip1)&IEM_INIT_ARGS_ALL,
+ srl[0], srl[1], srl[2],
+ x->x_gui.x_ldx, x->x_gui.x_ldy,
+ (*ip2)&IEM_FSTYLE_FLAGS_ALL, x->x_gui.x_fontsize,
+ bflcol[0], bflcol[1], bflcol[2],
+ x->x_val, x->x_steady);
+ binbuf_addv(b, ";");
+}
+
+void knob_check_height(t_knob *x, int h)
+{
+ if(h < IEM_SL_MINSIZE)
+ h = IEM_SL_MINSIZE;
+ x->x_gui.x_h = h;
+ if(x->x_val > (x->x_gui.x_h*100 - 100))
+ {
+ x->x_pos = x->x_gui.x_h*100 - 100;
+ x->x_val = x->x_pos;
+ }
+ if(x->x_lin0_log1)
+ x->x_k = log(x->x_max/x->x_min)/(double)(x->x_gui.x_h - 1);
+ else
+ x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 1);
+}
+
+void knob_check_minmax(t_knob *x, double min, double max)
+{
+ if(x->x_lin0_log1)
+ {
+ if((min == 0.0)&&(max == 0.0))
+ max = 1.0;
+ if(max > 0.0)
+ {
+ if(min <= 0.0)
+ min = 0.01*max;
+ }
+ else
+ {
+ if(min > 0.0)
+ max = 0.01*min;
+ }
+ }
+ x->x_min = min;
+ x->x_max = max;
+ if(x->x_min > x->x_max) /* bugfix */
+ x->x_gui.x_isa.x_reverse = 1;
+ else
+ x->x_gui.x_isa.x_reverse = 0;
+ if(x->x_lin0_log1)
+ x->x_k = log(x->x_max/x->x_min)/(double)(x->x_gui.x_h - 1);
+ else
+ x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 1);
+}
+
+static void knob_properties(t_gobj *z, t_glist *owner)
+{
+ t_knob *x = (t_knob *)z;
+ char buf[800];
+ t_symbol *srl[3];
+
+ iemgui_properties(&x->x_gui, srl);
+
+ sprintf(buf, "pdtk_iemgui_dialog %%s KNOB \
+ --------dimensions(pix)(pix):-------- %d %d NONE: %d %d height: \
+ -----------output-range:----------- %g left: %g right: %g \
+ %d lin log %d %d empty %d \
+ %s %s \
+ %s %d %d \
+ %d %d \
+ %d %d %d\n",
+ x->x_gui.x_w, IEM_SL_MINSIZE, x->x_gui.x_h, IEM_GUI_MINSIZE,
+ x->x_min, x->x_max, 0.0,/*no_schedule*/
+ x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/
+ srl[0]->s_name, srl[1]->s_name,
+ srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy,
+ x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize,
+ 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol);
+ gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf);
+}
+
+static void knob_bang(t_knob *x)
+{
+ double out;
+
+ if(x->x_lin0_log1)
+ out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01);
+ else
+ out = (double)(x->x_val)*0.01*x->x_k + x->x_min;
+ if((out < 1.0e-10)&&(out > -1.0e-10))
+ out = 0.0;
+ //post("knob_bang -- x_k: %f", x->x_k);
+
+ outlet_float(x->x_gui.x_obj.ob_outlet, out);
+ if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing)
+ pd_float(x->x_gui.x_snd->s_thing, out);
+}
+
+static void knob_dialog(t_knob *x, t_symbol *s, int argc, t_atom *argv)
+{
+ t_symbol *srl[3];
+ int w = (int)atom_getintarg(0, argc, argv);
+ int h = (int)atom_getintarg(1, argc, argv);
+ double min = (double)atom_getfloatarg(2, argc, argv);
+ double max = (double)atom_getfloatarg(3, argc, argv);
+ int lilo = (int)atom_getintarg(4, argc, argv);
+ int steady = (int)atom_getintarg(17, argc, argv);
+ int sr_flags;
+
+ if(lilo != 0) lilo = 1;
+ x->x_lin0_log1 = lilo;
+ if(steady)
+ x->x_steady = 1;
+ else
+ x->x_steady = 0;
+ sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv);
+ x->x_gui.x_h = iemgui_clip_size(w);
+ knob_check_height(x, h);
+ knob_check_minmax(x, min, max);
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG);
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags);
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
+}
+
+static void knob_motion(t_knob *x, t_floatarg dx, t_floatarg dy)
+{
+ int old = x->x_val;
+
+ if(x->x_gui.x_fsf.x_finemoved)
+ x->x_pos -= (int)dy;
+ else
+ x->x_pos -= 100*(int)dy;
+ x->x_val = x->x_pos;
+ if(x->x_val > (100*x->x_gui.x_h - 100))
+ {
+ x->x_val = 100*x->x_gui.x_h - 100;
+ x->x_pos += 50;
+ x->x_pos -= x->x_pos%100;
+ }
+ if(x->x_val < 0)
+ {
+ x->x_val = 0;
+ x->x_pos -= 50;
+ x->x_pos -= x->x_pos%100;
+ }
+ if(old != x->x_val)
+ {
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
+ knob_bang(x);
+ }
+}
+
+static void knob_click(t_knob *x, t_floatarg xpos, t_floatarg ypos,
+ t_floatarg shift, t_floatarg ctrl, t_floatarg alt)
+{
+ if(!x->x_steady)
+ x->x_val = (int)(100.0 * (x->x_gui.x_h + text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist) - ypos));
+ if(x->x_val > (100*x->x_gui.x_h - 100))
+ x->x_val = 100*x->x_gui.x_h - 100;
+ if(x->x_val < 0)
+ x->x_val = 0;
+ x->x_pos = x->x_val;
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
+ knob_bang(x);
+ glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, (t_glistmotionfn)knob_motion,
+ 0, xpos, ypos);
+}
+
+static int knob_newclick(t_gobj *z, struct _glist *glist,
+ int xpix, int ypix, int shift, int alt, int dbl, int doit)
+{
+ t_knob* x = (t_knob *)z;
+
+ if(doit)
+ {
+ knob_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift,
+ 0, (t_floatarg)alt);
+ if(shift)
+ x->x_gui.x_fsf.x_finemoved = 1;
+ else
+ x->x_gui.x_fsf.x_finemoved = 0;
+ }
+ return (1);
+}
+
+static void knob_set(t_knob *x, t_floatarg f)
+{
+ double g;
+
+ if(x->x_gui.x_isa.x_reverse) /* bugfix */
+ {
+ if(f > x->x_min)
+ f = x->x_min;
+ if(f < x->x_max)
+ f = x->x_max;
+ }
+ else
+ {
+ if(f > x->x_max)
+ f = x->x_max;
+ if(f < x->x_min)
+ f = x->x_min;
+ }
+ if(x->x_lin0_log1)
+ g = log(f/x->x_min)/x->x_k;
+ else
+ g = (f - x->x_min) / x->x_k;
+ //post("knob_set f: %f", f );
+ //post("knob_set g: %f", g );
+ x->x_val = (int)(100.0*g + 0.49999);
+ // x->x_val = (int)(100.0*g);
+ x->x_pos = x->x_val;
+ //post("knob_set x_val: %f", x->x_val );
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
+}
+
+static void knob_float(t_knob *x, t_floatarg f)
+{
+ /* post("knob_set infloat f: %f", f ); */
+ knob_set(x, f);
+ if(x->x_gui.x_fsf.x_put_in2out)
+ knob_bang(x);
+}
+
+static void knob_size(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{
+ x->x_gui.x_h = iemgui_clip_size((int)atom_getintarg(0, ac, av));
+ if(ac > 1)
+ knob_check_height(x, (int)atom_getintarg(1, ac, av));
+ iemgui_size((void *)x, &x->x_gui);
+}
+
+static void knob_delta(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{iemgui_delta((void *)x, &x->x_gui, s, ac, av);}
+
+static void knob_pos(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{iemgui_pos((void *)x, &x->x_gui, s, ac, av);}
+
+static void knob_range(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{
+ knob_check_minmax(x, (double)atom_getfloatarg(0, ac, av),
+ (double)atom_getfloatarg(1, ac, av));
+}
+
+static void knob_color(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{iemgui_color((void *)x, &x->x_gui, s, ac, av);}
+
+static void knob_send(t_knob *x, t_symbol *s)
+{iemgui_send(x, &x->x_gui, s);}
+
+static void knob_receive(t_knob *x, t_symbol *s)
+{iemgui_receive(x, &x->x_gui, s);}
+
+static void knob_label(t_knob *x, t_symbol *s)
+{iemgui_label((void *)x, &x->x_gui, s);}
+
+static void knob_label_pos(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);}
+
+static void knob_label_font(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);}
+
+static void knob_log(t_knob *x)
+{
+ x->x_lin0_log1 = 1;
+ knob_check_minmax(x, x->x_min, x->x_max);
+}
+
+static void knob_lin(t_knob *x)
+{
+ x->x_lin0_log1 = 0;
+ x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_h - 1);
+}
+
+static void knob_init(t_knob *x, t_floatarg f)
+{
+ x->x_gui.x_isa.x_loadinit = (f==0.0)?0:1;
+}
+
+static void knob_steady(t_knob *x, t_floatarg f)
+{
+ x->x_steady = (f==0.0)?0:1;
+}
+
+static void knob_loadbang(t_knob *x)
+{
+ /* WARNING: this is a kludge to get this object building on
+ Windows. Currently, the linker fails on the symbol
+ "sys_noloadbang". <hans@at.or.at>
+ */
+#ifdef _WIN32
+ if(x->x_gui.x_isa.x_loadinit)
+#else
+ if(!sys_noloadbang && x->x_gui.x_isa.x_loadinit)
+#endif
+ {
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE);
+ knob_bang(x);
+ }
+}
+
+/*
+static void knob_list(t_knob *x, t_symbol *s, int ac, t_atom *av)
+{
+ int l=iemgui_list((void *)x, &x->x_gui, s, ac, av);
+
+ if(l < 0)
+ {
+ if(IS_A_FLOAT(av,0))
+ knob_float(x, atom_getfloatarg(0, ac, av));
+ }
+ else if(l > 0)
+ {
+ (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE);
+ canvas_fixlinesfor(x->x_gui.x_glist, (t_text*)x);
+ }
+}
+*/
+
+static void *knob_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_knob *x = (t_knob *)pd_new(knob_class);
+ int bflcol[]={-262144, -1, -1};
+ t_symbol *srl[3];
+ int w=IEM_KNOB_DEFAULTSIZE, h=IEM_KNOB_DEFAULTSIZE;
+ int lilo=0, ldx=0, ldy=-8;
+ int fs=8, v=0, steady=1;
+ double min=0.0, max=(double)(IEM_SL_DEFAULTSIZE-1);
+ char str[144];
+
+ //srl[0] = gensym("empty");
+ //srl[1] = gensym("empty");
+ //srl[2] = gensym("empty");
+
+ iem_inttosymargs(&x->x_gui.x_isa, 0);
+ iem_inttofstyle(&x->x_gui.x_fsf, 0);
+
+
+ if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)
+ &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3)
+ &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5)
+ &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6))
+ &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7))
+ &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8))
+ &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10)
+ &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13)
+ &&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16))
+ {
+ w = (int)atom_getintarg(0, argc, argv);
+ h = (int)atom_getintarg(1, argc, argv);
+ min = (double)atom_getfloatarg(2, argc, argv);
+ max = (double)atom_getfloatarg(3, argc, argv);
+ lilo = (int)atom_getintarg(4, argc, argv);
+ iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv));
+ iemgui_new_getnames(&x->x_gui, 6, argv);
+ ldx = (int)atom_getintarg(9, argc, argv);
+ ldy = (int)atom_getintarg(10, argc, argv);
+ iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv));
+ fs = (int)atom_getintarg(12, argc, argv);
+ bflcol[0] = (int)atom_getintarg(13, argc, argv);
+ bflcol[1] = (int)atom_getintarg(14, argc, argv);
+ bflcol[2] = (int)atom_getintarg(15, argc, argv);
+ v = (int)atom_getintarg(16, argc, argv);
+ }
+ else iemgui_new_getnames(&x->x_gui, 6, 0);
+ if((argc == 18)&&IS_A_FLOAT(argv,17))
+ steady = (int)atom_getintarg(17, argc, argv);
+
+ x->x_gui.x_draw = (t_iemfunptr)knob_draw;
+
+ x->x_gui.x_fsf.x_snd_able = 1;
+ x->x_gui.x_fsf.x_rcv_able = 1;
+
+ x->x_gui.x_glist = (t_glist *)canvas_getcurrent();
+ if(x->x_gui.x_isa.x_loadinit)
+ x->x_val = v;
+ else
+ x->x_val = 0;
+ x->x_pos = x->x_val;
+ if(lilo != 0) lilo = 1;
+ x->x_lin0_log1 = lilo;
+ if(steady != 0) steady = 1;
+ x->x_steady = steady;
+ if (!strcmp(x->x_gui.x_snd->s_name, "empty"))
+ x->x_gui.x_fsf.x_snd_able = 0;
+ if (!strcmp(x->x_gui.x_rcv->s_name, "empty"))
+ x->x_gui.x_fsf.x_rcv_able = 0;
+ if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica");
+ else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times");
+ else { x->x_gui.x_fsf.x_font_style = 0;
+ strcpy(x->x_gui.x_font, "courier"); }
+ if(x->x_gui.x_fsf.x_rcv_able)
+ pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
+ x->x_gui.x_ldx = ldx;
+ x->x_gui.x_ldy = ldy;
+ if(fs < 4)
+ fs = 4;
+ x->x_gui.x_fontsize = fs;
+ x->x_gui.x_h = iemgui_clip_size(h);
+ knob_check_height(x, w);
+ knob_check_minmax(x, min, max);
+ iemgui_all_colfromload(&x->x_gui, bflcol);
+ //x->x_thick = 0;
+ iemgui_verify_snd_ne_rcv(&x->x_gui);
+ outlet_new(&x->x_gui.x_obj, &s_float);
+ return (x);
+}
+
+
+
+static void knob_free(t_knob *x)
+{
+ if(x->x_gui.x_fsf.x_selected)
+ pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym);
+ if(x->x_gui.x_fsf.x_rcv_able)
+ pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv);
+ gfxstub_deleteforkey(x);
+}
+
+void knob_setup(void)
+{
+ knob_class = class_new(gensym("knob"), (t_newmethod)knob_new,
+ (t_method)knob_free, sizeof(t_knob), 0, A_GIMME, 0);
+ class_addcreator((t_newmethod)knob_new, gensym("knob"), A_GIMME, 0);
+ class_addbang(knob_class,knob_bang);
+ class_addfloat(knob_class,knob_float);
+
+ /* class_addlist(knob_class, knob_list); */
+ class_addmethod(knob_class, (t_method)knob_click, gensym("click"),
+ A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0);
+ class_addmethod(knob_class, (t_method)knob_motion, gensym("motion"),
+ A_FLOAT, A_FLOAT, 0);
+ class_addmethod(knob_class, (t_method)knob_dialog, gensym("dialog"),
+ A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_loadbang, gensym("loadbang"), 0);
+ class_addmethod(knob_class, (t_method)knob_set, gensym("set"), A_FLOAT, 0);
+ class_addmethod(knob_class, (t_method)knob_size, gensym("size"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_delta, gensym("delta"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_pos, gensym("pos"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_range, gensym("range"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_color, gensym("color"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_send, gensym("send"), A_DEFSYM, 0);
+ class_addmethod(knob_class, (t_method)knob_receive, gensym("receive"), A_DEFSYM, 0);
+ class_addmethod(knob_class, (t_method)knob_label, gensym("label"), A_DEFSYM, 0);
+ class_addmethod(knob_class, (t_method)knob_label_pos, gensym("label_pos"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_label_font, gensym("label_font"), A_GIMME, 0);
+ class_addmethod(knob_class, (t_method)knob_log, gensym("log"), 0);
+ class_addmethod(knob_class, (t_method)knob_lin, gensym("lin"), 0);
+ class_addmethod(knob_class, (t_method)knob_init, gensym("init"), A_FLOAT, 0);
+ class_addmethod(knob_class, (t_method)knob_steady, gensym("steady"), A_FLOAT, 0);
+ if(!iemgui_key_sym)
+ iemgui_key_sym = gensym("#keyname");
+ knob_widgetbehavior.w_getrectfn = knob_getrect;
+ knob_widgetbehavior.w_displacefn = iemgui_displace;
+ knob_widgetbehavior.w_selectfn = iemgui_select;
+ knob_widgetbehavior.w_activatefn = NULL;
+ knob_widgetbehavior.w_deletefn = iemgui_delete;
+ knob_widgetbehavior.w_visfn = iemgui_vis;
+ knob_widgetbehavior.w_clickfn = knob_newclick;
+#if PD_MINOR_VERSION < 37 /* TODO: remove old behaviour in exactly 2 months from now */
+ knob_widgetbehavior.w_propertiesfn = knob_properties;;
+ knob_widgetbehavior.w_savefn = knob_save;
+#else
+ class_setpropertiesfn(knob_class, &knob_properties);
+ class_setsavefn(knob_class, &knob_save);
+#endif
+ class_setwidget(knob_class, &knob_widgetbehavior);
+ class_sethelpsymbol(knob_class, gensym("knob"));
+}
diff --git a/popup-help.pd b/popup-help.pd
new file mode 100644
index 0000000..3142ff8
--- /dev/null
+++ b/popup-help.pd
@@ -0,0 +1,39 @@
+#N canvas 119 198 626 449 10;
+#X obj 106 340 popup 124 25 grey90 duh! one two three four five six
+seven eight nine ten eleven twelve thirteen i14 i15 i16 i17 i18 i19
+i20 i21 i22 i23 i24 i25 i26 i27 i28 i29 i30;
+#X obj 152 399 print index;
+#X msg 30 98 name popup;
+#X obj 239 399 print symbol;
+#X floatatom 163 292 5 0 0 0 - - -;
+#X text 14 43 Left outlet sends out a bang on load \, used to set default
+value. Using a loadbang to send a float will result in a crash.;
+#X msg 107 225 options;
+#X msg 100 176 options one two three four five six seven eight nine
+ten eleven twelve thirteen i14 i15 i16 i17 i18 i19 i20 i21 i22 i23
+i24 i25 i26 i27 i28 i29 i30;
+#X msg 118 251 append append-one append-two append-three;
+#X obj 106 372 route bang;
+#X msg 33 338 10;
+#X text 187 372 Choose 10 as the default value on load \, does send
+output.;
+#X msg 53 123 bgcolour #047992;
+#X msg 83 150 bgcolour grey90;
+#X symbolatom 223 315 10 0 0 0 - - -;
+#X text 209 289 Select by index;
+#X text 302 314 Select by symbol name;
+#X text 13 11 popup \, a popup menu for PD. Copyright Ben Bogart 2004
+\, 2005 Released under the GPL.;
+#X connect 0 0 9 0;
+#X connect 0 1 3 0;
+#X connect 2 0 0 0;
+#X connect 4 0 0 0;
+#X connect 6 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 0 0;
+#X connect 9 0 10 0;
+#X connect 9 1 1 0;
+#X connect 10 0 0 0;
+#X connect 12 0 0 0;
+#X connect 13 0 0 0;
+#X connect 14 0 0 1;
diff --git a/popup.c b/popup.c
new file mode 100644
index 0000000..7a9c899
--- /dev/null
+++ b/popup.c
@@ -0,0 +1,701 @@
+/* Popup menu widget for PD *
+ * Based on button from GGEE by Guenter Geiger *
+ * Copyright Ben Bogart 2004 ben@ekran.org *
+
+ * This program is distributed under the terms of the GNU General Public *
+ * License *
+
+ * popup is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+
+ * popup is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. */
+
+
+
+#include <m_pd.h>
+#include <g_canvas.h>
+#include <stdio.h>
+#include <string.h>
+
+
+#ifdef _MSC_VER
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#ifndef IOWIDTH
+#define IOWIDTH 4
+#endif
+
+#define MAX_OPTIONS 100
+
+typedef struct _popup
+{
+ t_object x_obj;
+
+ t_glist * x_glist;
+ t_outlet* out2;
+ int x_rect_width;
+ int x_rect_height;
+ t_symbol* x_sym;
+
+ int x_height;
+ int x_width;
+
+ int current_selection;
+ int x_num_options;
+ t_symbol* x_colour;
+ t_symbol* x_name;
+
+ t_symbol** x_options;
+ int x_maxoptions;
+
+ int initialized; /* 1 when we are allowed to draw, 0 otherwise */
+ int x_disabled; /* when disabled, graphical chosing is prohibited */
+} t_popup;
+
+/* widget helper functions */
+
+/* Append " x " to the following line to show debugging messages */
+#define DEBUG(x)
+
+
+static void draw_inlets(t_popup *x, t_glist *glist, int firsttime, int nin, int nout)
+{
+ /* outlets */
+ int n = nin;
+ int nplus, i;
+ nplus = (n == 1 ? 1 : n-1);
+ DEBUG(post("draw inlet");)
+ for (i = 0; i < n; i++)
+ {
+ int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
+ if (firsttime)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags {%lxo%d %lxo}\n",
+ glist_getcanvas(glist),
+ onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2,
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1,
+ x, i, x);
+ else
+ sys_vgui(".x%lx.c coords %lxo%d %d %d %d %d\n",
+ glist_getcanvas(glist), x, i,
+ onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 2,
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist) + x->x_rect_height-1);
+ }
+ /* inlets */
+ n = nout;
+ nplus = (n == 1 ? 1 : n-1);
+ for (i = 0; i < n; i++)
+ {
+ int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH) * i / nplus;
+ if (firsttime)
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags {%lxi%d %lxi}\n",
+ glist_getcanvas(glist),
+ onset, text_ypix(&x->x_obj, glist)-2,
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist)-1,
+ x, i, x);
+ else
+ sys_vgui(".x%lx.c coords %lxi%d %d %d %d %d\n",
+ glist_getcanvas(glist), x, i,
+ onset, text_ypix(&x->x_obj, glist),
+ onset + IOWIDTH, text_ypix(&x->x_obj, glist)-1);
+
+ }
+ DEBUG(post("draw inlet end");)
+}
+
+
+static void draw_handle(t_popup *x, t_glist *glist, int firsttime) {
+
+ DEBUG(post("draw_handle start");)
+ int onset = text_xpix(&x->x_obj, glist) + (x->x_rect_width - IOWIDTH);
+
+ if (firsttime) {
+ sys_vgui(".x%lx.c create rectangle %d %d %d %d -tags %lxhandle\n",
+ glist_getcanvas(glist),
+ onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
+ onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4,
+ x);
+ }
+ else {
+ sys_vgui(".x%lx.c coords %lxhandle %d %d %d %d\n",
+ glist_getcanvas(glist), x,
+ onset, text_ypix(&x->x_obj, glist) + x->x_rect_height - 12,
+ onset + IOWIDTH-2, text_ypix(&x->x_obj, glist) + x->x_rect_height-4);
+ }
+ DEBUG(post("draw_handle end");)
+}
+
+static void create_widget(t_popup *x, t_glist *glist)
+{
+ DEBUG(post("create_widget start");)
+
+ char text[MAXPDSTRING];
+ int len,i;
+ t_symbol* temp_name;
+ t_canvas *canvas=glist_getcanvas(glist);
+ x->x_rect_width = x->x_width;
+ x->x_rect_height = x->x_height+2;
+
+ /* Create menubutton and empty menu widget -- maybe the menu should be created elseware?*/
+
+ /* draw using the last name if it was selected otherwise use default name. */
+ if(x->current_selection < 0)
+ {
+ temp_name = x->x_name;
+ } else {
+ temp_name = x->x_options[x->current_selection];
+ }
+
+ /* Seems we have to delete the widget in case it already exists (Provided by Guenter)*/
+ if(x->initialized)
+ {
+ sys_vgui("destroy .x%lx.c.s%lx\n",glist_getcanvas(glist),x);
+
+ sys_vgui("set %lxw .x%lx.c.s%lx ; menubutton $%lxw -relief raised -background \"%s\" -text \"%s\" -direction flush -menu $%lxw.menu ; menu $%lxw.menu -tearoff 0\n",
+ x,canvas,x,x,x->x_colour->s_name,temp_name->s_name,x,x);
+
+ for(i=0 ; i<x->x_num_options ; i++)
+ {
+ sys_vgui(".x%lx.c.s%lx.menu add command -label \"%s\" -command {.x%lx.c.s%lx configure -text \"%s\" ; popup_sel%lx \"%d\"} \n",
+ canvas, x, x->x_options[i]->s_name, canvas, x, x->x_options[i]->s_name, x, i);
+ }
+ }
+
+ DEBUG(post("id: .x%lx.c.s%lx", canvas, x);)
+ DEBUG(post("create_widget end");)
+}
+
+static void popup_drawme(t_popup *x, t_glist *glist, int firsttime)
+{
+ t_canvas *canvas=glist_getcanvas(glist);
+ DEBUG(post("drawme start");)
+
+ /* by drawing, we "initialize" the popup */
+ x->initialized=1;
+
+ DEBUG(post("drawme %d",firsttime);)
+ if (firsttime) {
+ DEBUG(post("glist %lx canvas %lx",x->x_glist,canvas);)
+ create_widget(x,glist);
+ x->x_glist = canvas;
+ sys_vgui(".x%lx.c create window %d %d -width %d -height %d -anchor nw -window .x%lx.c.s%lx -tags %lxS\n",
+ canvas,text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), x->x_width, x->x_height, x->x_glist,x,x);
+
+ }
+ else {
+ sys_vgui(".x%lx.c coords %lxS %d %d\n",
+ canvas, x,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist));
+ }
+ draw_inlets(x, glist, firsttime, 2,2);
+ // draw_handle(x, glist, firsttime);
+ sys_vgui(".x%lx.c.s%lx configure -state \"%s\"\n", canvas, x, x->x_disabled?"disabled":"active");
+
+
+ // Output a bang to first outlet when we're ready to receive float messages the first time!.
+ // Too bad this is NOT always the first time... window shading makes the bang go out again. :(
+ if(firsttime) {outlet_bang(x->x_obj.ob_outlet);}
+
+ DEBUG(post("drawme end");)
+}
+
+
+static void popup_erase(t_popup* x,t_glist* glist)
+{
+ int n;
+
+ DEBUG(post("erase start");)
+ if(x->initialized){
+ sys_vgui("destroy .x%lx.c.s%lx\n",glist_getcanvas(glist),x);
+
+ sys_vgui(".x%lx.c delete %lxS\n",glist_getcanvas(glist), x);
+
+ /* inlets and outlets */
+
+ sys_vgui(".x%lx.c delete %lxi\n",glist_getcanvas(glist),x); /* Added tag for all inlets of one instance */
+ sys_vgui(".x%lx.c delete %lxo\n",glist_getcanvas(glist),x); /* Added tag for all outlets of one instance */
+ sys_vgui(".x%lx.c delete %lxhandle\n",glist_getcanvas(glist),x,0);
+ }
+
+ DEBUG(post("erase end");)
+}
+
+
+
+/* ------------------------ popup widgetbehaviour----------------------------- */
+
+
+static void popup_getrect(t_gobj *z, t_glist *owner,
+ int *xp1, int *yp1, int *xp2, int *yp2)
+{
+// DEBUG(post("getrect start");)
+
+ int width, height;
+ t_popup* s = (t_popup*)z;
+
+ width = s->x_rect_width;
+ height = s->x_rect_height;
+ *xp1 = text_xpix(&s->x_obj, owner);
+ *yp1 = text_ypix(&s->x_obj, owner) - 1;
+ *xp2 = text_xpix(&s->x_obj, owner) + width;
+ *yp2 = text_ypix(&s->x_obj, owner) + height;
+
+// DEBUG(post("getrect end");)
+}
+
+static void popup_displace(t_gobj *z, t_glist *glist,
+ int dx, int dy)
+{
+ t_popup *x = (t_popup *)z;
+ DEBUG(post("displace start");)
+ x->x_obj.te_xpix += dx;
+ x->x_obj.te_ypix += dy;
+ if (glist_isvisible(glist))
+ {
+ if(x->initialized)sys_vgui(".x%lx.c coords %lxSEL %d %d %d %d\n",
+ glist_getcanvas(glist), x,
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1,
+ text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height-2);
+
+ popup_drawme(x, glist, 0);
+ canvas_fixlinesfor(glist,(t_text*) x);
+ }
+ DEBUG(post("displace end");)
+}
+
+static void popup_select(t_gobj *z, t_glist *glist, int state)
+{
+ DEBUG(post("select start");)
+
+ t_popup *x = (t_popup *)z;
+ if(x->initialized){
+ if (state) {
+ sys_vgui(".x%lx.c create rectangle \
+%d %d %d %d -tags %lxSEL -outline blue\n",
+ glist_getcanvas(glist),
+ text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)-1,
+ text_xpix(&x->x_obj, glist) + x->x_rect_width, text_ypix(&x->x_obj, glist) + x->x_rect_height-2,
+ x);
+ }
+ else {
+ sys_vgui(".x%lx.c delete %lxSEL\n",
+ glist_getcanvas(glist), x);
+ }
+ }
+
+ DEBUG(post("select end");)
+}
+
+static void popup_activate(t_gobj *z, t_glist *glist, int state)
+{
+ DEBUG(post("activate commented out!");)
+
+/* What does this do, why commented out?
+ t_text *x = (t_text *)z;
+ t_rtext *y = glist_findrtext(glist, x);
+ if (z->g_pd != gatom_class) rtext_activate(y, state);*/
+}
+
+static void popup_delete(t_gobj *z, t_glist *glist)
+{
+ DEBUG(post("delete start");)
+
+ t_text *x = (t_text *)z;
+ canvas_deletelinesfor(glist, x);
+
+ DEBUG(post("delete end");)
+}
+
+
+static void popup_vis(t_gobj *z, t_glist *glist, int vis)
+{
+ t_popup* s = (t_popup*)z;
+
+ DEBUG(post("vis: %d",vis);)
+ if (vis) {
+ popup_drawme(s, glist, 1);
+ }
+ else {
+ popup_erase(s,glist);
+ }
+
+ DEBUG(post("vis end");)
+}
+
+static void popup_save(t_gobj *z, t_binbuf *b);
+
+t_widgetbehavior popup_widgetbehavior = {
+ w_getrectfn: popup_getrect,
+ w_displacefn: popup_displace,
+ w_selectfn: popup_select,
+ w_activatefn: popup_activate,
+ w_deletefn: popup_delete,
+ w_visfn: popup_vis,
+#if PD_MINOR_VERSION < 37
+ w_savefn: popup_save,
+#endif
+ w_clickfn: NULL,
+#if PD_MINOR_VERSION < 37
+ w_propertiesfn: NULL,
+#endif
+
+};
+
+static void popup_output(t_popup* x, t_floatarg popup_index)
+{
+ DEBUG(post("output start");)
+
+ x->current_selection = popup_index;
+ outlet_symbol(x->out2, x->x_options[(int)popup_index]);
+ outlet_float(x->x_obj.ob_outlet, popup_index);
+}
+
+
+static void popup_save(t_gobj *z, t_binbuf *b)
+{
+ DEBUG(post("save start");)
+
+ int i;
+ t_popup *x = (t_popup *)z;
+
+ binbuf_addv(b, "ssiisiiss", gensym("#X"), gensym("obj"),
+ x->x_obj.te_xpix, x->x_obj.te_ypix ,
+ atom_getsymbol(binbuf_getvec(x->x_obj.te_binbuf)),
+ x->x_width, x->x_height, x->x_colour, x->x_name);
+ /* Loop for menu items */
+ for(i=0 ; i<x->x_num_options ; i++)
+ {
+ binbuf_addv(b, "s", x->x_options[i]);
+ }
+ binbuf_addv(b, ";");
+
+ DEBUG(post("vis end");)
+}
+
+/* function to change the popup's menu */
+static void popup_options(t_popup* x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("options start");)
+
+ int i;
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+
+ x->x_num_options = argc;
+
+ /* delete old menu items */
+ if(visible)sys_vgui(".x%lx.c.s%lx.menu delete 0 end \n", x->x_glist, x);
+
+ if(argc>x->x_maxoptions){
+ /* resize the options-array */
+ if(x->x_options)freebytes(x->x_options, sizeof(t_symbol*)*x->x_maxoptions);
+ x->x_maxoptions=argc;
+ x->x_options=(t_symbol**)getbytes(sizeof(t_symbol*)*x->x_maxoptions);
+ }
+
+ for(i=0 ; i<argc ; i++)
+ {
+ x->x_options[i] = atom_getsymbol(argv+i);
+ if(visible)sys_vgui(".x%lx.c.s%lx.menu add command -label \"%s\" -command {.x%lx.c.s%lx configure -text \"%s\" ; popup_sel%lx \"%d\"} \n",
+ x->x_glist, x, x->x_options[i]->s_name, x->x_glist, x, x->x_options[i]->s_name, x, i);
+ }
+
+ DEBUG(post("options end");)
+}
+
+/* function to change colour of popup background */
+static void popup_bgcolour(t_popup* x, t_symbol* col)
+{
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+ DEBUG(post("bgcolour start");)
+
+ x->x_colour = col;
+ if(visible)sys_vgui(".x%lx.c.s%lx configure -background \"%s\"\n", x->x_glist, x, col->s_name);
+}
+
+/* Function to change name of popup */
+static void popup_name(t_popup* x, t_symbol *name)
+{
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+ DEBUG(post("name start");)
+
+ x->x_name = name;
+ if(visible)sys_vgui(".x%lx.c.s%lx configure -text \"%s\"\n", x->x_glist, x, name->s_name);
+}
+
+/* Function to select a menu option by inlet */
+static void popup_iselect(t_popup* x, t_floatarg item)
+{
+ DEBUG(post("iselect start");)
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+
+ int i=(int)item;
+ if( i<x->x_num_options && i>=0)
+ {
+ if(visible)sys_vgui(".x%lx.c.s%lx configure -text \"%s\" ; popup_sel%lx \"%d\" \n",
+ glist_getcanvas(x->x_glist), x, x->x_options[i]->s_name,x, i);
+ else popup_output(x, i);
+
+ } else {
+ pd_error(x, "popup: Valid menu selections are from %d to %d\npopup: You entered %d.", 0, x->x_num_options-1, i);
+ }
+
+ DEBUG(post("iselect end");)
+}
+
+/* Function to choose value via symbol name */
+static void popup_symselect(t_popup* x, t_symbol *s)
+{
+ int i,match=0;
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+
+ /* Compare inlet symbol to each option */
+ for(i=0; i<x->x_num_options; i++)
+ {
+ if(x->x_options[i]->s_name == s->s_name)
+ {
+ if(visible)sys_vgui(".x%lx.c.s%lx configure -text \"%s\" ; popup_sel%lx \"%d\" \n",
+ glist_getcanvas(x->x_glist), x, x->x_options[i]->s_name,x, i);
+ else popup_output(x, i);
+ match = 1;
+ break;
+ }
+ }
+
+ if(match != 1)
+ post("popup: '%s' is not an available option.", s->s_name);
+
+}
+
+/* Function to choose value via name/index but without outputting it*/
+static void popup_set(t_popup* x, t_symbol *S, int argc, t_atom*argv)
+{
+ if(!argc)return;
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+
+ if(argv->a_type==A_FLOAT)
+ {
+ int i=atom_getint(argv);
+ if( i<x->x_num_options && i>=0)
+ {
+ x->current_selection = i;
+ if(visible)
+ sys_vgui(".x%lx.c.s%lx configure -text \"%s\"\n",
+ glist_getcanvas(x->x_glist), x, x->x_options[i]->s_name);
+ } else {
+ error("popup: Valid menu selections are from %d to %d\npopup: You entered %d.", 0, x->x_num_options-1, i);
+ }
+ } else if(argv->a_type==A_SYMBOL)
+ {
+ int i;
+ t_symbol*s=atom_getsymbol(argv);
+ /* Compare inlet symbol to each option */
+ for(i=0; i<x->x_num_options; i++)
+ {
+ if(x->x_options[i]->s_name == s->s_name)
+ {
+ x->current_selection = i;
+ if(visible)sys_vgui(".x%lx.c.s%lx configure -text \"%s\"\n",
+ glist_getcanvas(x->x_glist), x, x->x_options[i]->s_name);
+ return;
+ }
+ }
+ error("popup: '%s' is not an available option.", s->s_name);
+ } else
+ {
+ pd_error(x, "popup: can only 'set' symbols or floats");
+ }
+}
+
+/* Function to append symbols to popup list */
+static void popup_append(t_popup* x, t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("append start");)
+
+ int i, new_limit;
+ int visible=(x->x_glist)?glist_isvisible(x->x_glist):0;
+
+ new_limit = x->x_num_options + argc;
+ if(new_limit>x->x_maxoptions){
+ t_symbol**dummy;
+ int new_size=new_limit*2;
+ DEBUG(post("resizing options");)
+ dummy=(t_symbol**)getbytes(sizeof(t_symbol*)*new_size);
+ if(dummy)
+ {
+ memcpy(dummy, x->x_options, sizeof(t_symbol*)*x->x_maxoptions);
+ freebytes(x->x_options, sizeof(t_symbol*)*x->x_maxoptions);
+ x->x_maxoptions=new_size;
+ x->x_options=dummy;
+ } else {
+ error("popup: no memory for options");
+ return;
+ }
+ }
+
+ for(i=x->x_num_options ; i<new_limit ; i++)
+ {
+ x->x_options[i] = atom_getsymbol(argv+i-x->x_num_options);
+ if(visible)sys_vgui(".x%lx.c.s%lx.menu add command -label \"%s\" -command {.x%lx.c.s%lx configure -text \"%s\" ; popup_sel%lx \"%d\"} \n",
+ x->x_glist, x, x->x_options[i]->s_name, x->x_glist, x, x->x_options[i]->s_name, x, i);
+ }
+
+ x->x_num_options = new_limit;
+
+ DEBUG(post("append end");)
+}
+
+static void popup_disable(t_popup*x, t_float f){
+ x->x_disabled=(f>0.f);
+ if(x->x_glist && glist_isvisible(x->x_glist)){
+ t_canvas *canvas=glist_getcanvas(x->x_glist);
+ sys_vgui(".x%lx.c.s%lx configure -state \"%s\"\n", canvas, x, x->x_disabled?"disabled":"active");
+ }
+}
+
+
+
+static t_class *popup_class;
+
+static void popup_free(t_popup*x)
+{
+ if(x->x_options)freebytes(x->x_options, sizeof(t_symbol*)*x->x_maxoptions);
+}
+
+
+static void *popup_new(t_symbol *s, int argc, t_atom *argv)
+{
+ DEBUG(post("popup new start");)
+
+ t_popup *x = (t_popup *)pd_new(popup_class);
+ int i;
+ char buf[256];
+
+ x->x_glist = (t_glist*)NULL;
+
+ x->x_height = 25;
+ x->current_selection = -1;
+
+ x->x_maxoptions=MAX_OPTIONS;
+ x->x_options=(t_symbol**)getbytes(sizeof(t_symbol*)*x->x_maxoptions);
+
+
+ x->x_width = 124;
+ x->x_height = 25;
+ x->x_num_options = 1;
+ x->x_colour = gensym("#ffffff");
+ x->x_name = gensym("popup");
+
+ x->x_options[0] = gensym("option");
+
+ x->initialized=0;
+
+ x->x_disabled=0;
+
+ switch(argc){
+ case 0: break; /* just use default values */
+ case 1:
+ post("popup: You must enter at least 5 arguments. Default values used.\n\nArguments:\npopup [width] [height] [colour] [name] [option-1] [option-2] ...");
+ break;
+ default:
+ /* Copy args into structure */
+ x->x_num_options = argc-4;
+
+ for(i=0 ; i<x->x_num_options ; i++)
+ {
+ x->x_options[i] = atom_getsymbol( argv+(i+4) );
+ }
+ case 4:
+ x->x_name = atom_getsymbol(argv+3);
+ case 3:
+ x->x_colour = atom_getsymbol(argv+2);
+ case 2:
+ x->x_width =atom_getint(argv+0);
+ x->x_height=atom_getint(argv+1);
+ break;
+ }
+
+ /* Bind the recieve "popup%lx" to the widget outlet*/
+ sprintf(buf,"popup%lx", (long unsigned int)x);
+ x->x_sym = gensym(buf);
+ pd_bind(&x->x_obj.ob_pd, x->x_sym);
+
+ /* define proc in tcl/tk where "popup%p" is the receive, "output" is the method, and "$index" is an argument. */
+ sys_vgui("proc popup_sel%lx {index} {\n pdsend \"%s output $index \"\n }\n",
+ x, buf);
+
+ /* Add symbol inlet (hard to say how this actually works?? */
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("symbol"), gensym(""));
+ outlet_new(&x->x_obj, &s_float);
+ x->out2 = outlet_new(&x->x_obj, &s_symbol);
+
+DEBUG(post("popup new end");)
+
+ return (x);
+}
+
+void popup_setup(void) {
+
+ DEBUG(post("setup start");)
+
+ popup_class = class_new(gensym("popup"), (t_newmethod)popup_new, (t_method)popup_free,
+ sizeof(t_popup),0,A_GIMME,0);
+
+ class_addmethod(popup_class, (t_method)popup_output,
+ gensym("output"),
+ A_DEFFLOAT,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_name,
+ gensym("name"),
+ A_DEFSYMBOL,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_options,
+ gensym("options"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_bgcolour,
+ gensym("bgcolour"),
+ A_DEFSYMBOL,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_append,
+ gensym("append"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_set,
+ gensym("set"),
+ A_GIMME,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_symselect,
+ gensym(""),
+ A_DEFSYMBOL,
+ 0);
+
+ class_addmethod(popup_class, (t_method)popup_disable,
+ gensym("disable"),
+ A_FLOAT,
+ 0);
+
+ class_doaddfloat(popup_class, (t_method)popup_iselect);
+
+ //class_addsymbol(popup_class, (t_method)popup_symselect);
+
+ class_setwidget(popup_class,&popup_widgetbehavior);
+#if PD_MINOR_VERSION >= 37
+ class_setsavefn(popup_class,&popup_save);
+#endif
+
+ post("Popup v0.1 Ben Bogart.\nCVS: $Revision: 1.18 $ $Date: 2007-10-29 18:58:42 $");
+}
+
+
diff --git a/template-meta.pd b/template-meta.pd
new file mode 100644
index 0000000..2718900
--- /dev/null
+++ b/template-meta.pd
@@ -0,0 +1,6 @@
+#N canvas 15 49 200 200 10;
+#N canvas 25 49 420 300 META 1;
+#X text 13 41 NAME template;
+#X text 10 25 AUTHOR example@fsf.org;
+#X text 10 10 VERSION 0.0;
+#X restore 10 10 pd META;