--- /dev/null
+ 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>.
--- /dev/null
+
+date ver description of changes
+
+2015-12-29 1.3.2 - added inital ptouch-gtk - it is WITHOUT function
+ for now. I just have somewhere to start...
+
+2015-11-12 1.3.1 - small bugfix
+ - now using autotools
+
+2015-02-13 1.3 - merged ptouch-printpng and ptouch-printtext to one
+ single tool so that multiple texts and images can be
+ printed in one single pass.
+ - added ptouch_cutmark() function
+ - added initial gettext() support
+
+2015-01-05 1.2.3 - fixed a bug that did cut off chars which go below the
+ font baseline (like g,q,j,...)
+ Seems that gdImageStringFT() interprets the y coord
+ as baseline of the font (is this the case for all
+ fonts??) instead of the bottom most pixel.
+
+2014-12-20 1.2.2 - added support for printing up to 4 lines of text
+
+2014-11-01 1.2.1 - added support for PT-1230PC printer (not tested)
+
+2014-10-1? 1.2 - added tool 'ptouch-printtext' which can print labels
+ with one or two lines of text
+
+2014-10-11 1.1 - easier adding of (yet) unsupported p-touch printers
+ and tape widths
+ - code cleanup
+
+2014-10-08 1.0 Initial release
--- /dev/null
+AUTOMAKE_OPTIONS = subdir-objects
+AM_CPPFLAGS= -DLOCALEDIR='"$(localedir)"'
+AM_CFLAGS=-g -Wall -O3 -I$(top_srcdir)/include `pkg-config --cflags gtk+-3.0`
+SUBDIRS = po
+ACLOCAL_AMFLAGS = -I m4
+EXTRA_DIST = config.rpath m4/ChangeLog Makefile.old data/ptouch.ui
+bin_PROGRAMS=ptouch-print ptouch-gtk
+noinst_HEADERS=include/ptouch.h include/gettext.h
+ptouch_print_SOURCES=src/ptouch-print.c src/libptouch.c include/ptouch.h include/gettext.h
+ptouch_print_LDFLAGS=-lusb-1.0 -lgd
+ptouch_gtk_SOURCES=src/ptouch-gtk.c src/libptouch.c include/ptouch.h include/gettext.h
+ptouch_gtk_LDFLAGS=-lusb-1.0 -lgd `pkg-config --libs gtk+-3.0` -rdynamic
--- /dev/null
+
+See ChangeLog
--- /dev/null
+
+ptouch is a command line tool to print labels on Brother P-Touch
+printers on Linux.
+
+There is no need to install the printer via CUPS, the printer is accessed
+directly via libusb.
+
+The tool was written for and tested with the PT-2430PC, but it should also
+work with the PT-1230PC (untested so far).
+Maybe others work too (please report USB VID and PID so I can include support
+for further models, too).
+
+Further info can be found at:
+http://mockmoon-cybernetics.ch/computer/p-touch2430pc/
--- /dev/null
+#
+# ptouch-print - Print labels with images or text on a Brother P-Touch
+#
+# Copyright (C) 2015 Dominic Radermacher <dominic.radermacher@gmail.com>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ([2.69])
+AC_INIT([ptouch], [1.3.2], [dominic.radermacher@gmail.com])
+AC_CONFIG_SRCDIR([src/libptouch.c])
+AC_CONFIG_HEADERS([config.h])
+
+# Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+AM_INIT_AUTOMAKE
+AM_GNU_GETTEXT([external])
+AM_GNU_GETTEXT_VERSION(0.19)
+
+# Checks for libraries.
+AC_CHECK_LIB([gd], [gdImageStringFT])
+AC_CHECK_LIB([usb-1.0], [libusb_init])
+AC_CHECK_LIB([gtk-3], [gtk_init])
+
+# Checks for header files.
+AC_CHECK_HEADERS([fcntl.h libintl.h stdint.h stdlib.h string.h])
+AC_CHECK_HEADERS([gd.h], [], [AC_MSG_ERROR([libgd headers missing - maybe you need to install package gd-dev or gd-devel?])])
+AC_CHECK_HEADERS([libusb-1.0/libusb.h], [], [AC_MSG_ERROR([libusb headers missing - maybe you need to install package libusb-dev or libusb-devel?])])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([memset setlocale strpbrk strtol])
+
+AC_CONFIG_FILES([Makefile po/Makefile.in])
+AC_OUTPUT
--- /dev/null
+<?xml version="1.0"?>
+<interface>
+ <object class="GtkWindow" id="editorwindow">
+ <property name="visible">True</property>
+ <property name="title" translatable="yes">ptouch-print-gtk</property>
+ <property name="icon">/usr/share/pixmaps/ptouch-gtk.png</property>
+ <signal handler="on_window_destroy" name="delete_event"/>
+ <child>
+ <object class="GtkVBox" id="vbox1">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkScrolledWindow" id="previewscroll">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="vscrollbar_policy">never</property>
+ <property name="window_placement">bottom-right</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="resize_mode">queue</property>
+ <child>
+ <object class="GtkImage" id="preview">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">Preview area</property>
+ <property name="stock">gtk-missing-image</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="Line 1">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox2">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkEntry" id="entry1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <signal handler="update_preview" name="changed"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkFontButton" id="fontselect1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">Font for 1st line</property>
+ <property name="use_font">True</property>
+ <signal handler="update_preview" name="font_set"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>1st line</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">2</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="Line 2">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <child>
+ <object class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="left_padding">12</property>
+ <child>
+ <object class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkEntry" id="entry2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">•</property>
+ <signal handler="update_preview" name="changed"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox2">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkFontButton" id="fontselect2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">Font for 2nd line</property>
+ <property name="use_font">True</property>
+ <signal handler="update_preview" name="font_set"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"><b>2nd line</b></property>
+ <property name="use_markup">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="padding">2</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHBox" id="hbox4">
+ <property name="visible">True</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkButton" id="printbutton">
+ <property name="label">gtk-print</property>
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">Print</property>
+ <property name="use_stock">True</property>
+ <signal handler="print_all" name="clicked"/>
+ </object>
+ <packing>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="About">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">About this program</property>
+ <property name="use_stock">True</property>
+ <signal handler="show_about" name="clicked"/>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="quitbutton">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="tooltip-text" translatable="yes">Quit the program</property>
+ <property name="use_stock">True</property>
+ <signal handler="on_window_destroy" name="clicked"/>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
--- /dev/null
+/* Convenience header for conditional use of GNU <libintl.h>.
+ Copyright (C) 1995-1998, 2000-2002, 2004-2006, 2009-2011, 2015 Free
+ Software Foundation, Inc.
+
+ This program is free software: you can 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/>. */
+
+#ifndef _LIBGETTEXT_H
+#define _LIBGETTEXT_H 1
+
+/* NLS can be disabled through the configure --disable-nls option. */
+#if ENABLE_NLS
+
+/* Get declarations of GNU message catalog functions. */
+# include <libintl.h>
+
+/* You can set the DEFAULT_TEXT_DOMAIN macro to specify the domain used by
+ the gettext() and ngettext() macros. This is an alternative to calling
+ textdomain(), and is useful for libraries. */
+# ifdef DEFAULT_TEXT_DOMAIN
+# undef gettext
+# define gettext(Msgid) \
+ dgettext (DEFAULT_TEXT_DOMAIN, Msgid)
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+ dngettext (DEFAULT_TEXT_DOMAIN, Msgid1, Msgid2, N)
+# endif
+
+#else
+
+/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which
+ chokes if dcgettext is defined as a macro. So include it now, to make
+ later inclusions of <locale.h> a NOP. We don't include <libintl.h>
+ as well because people using "gettext.h" will not include <libintl.h>,
+ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h>
+ is OK. */
+#if defined(__sun)
+# include <locale.h>
+#endif
+
+/* Many header files from the libstdc++ coming with g++ 3.3 or newer include
+ <libintl.h>, which chokes if dcgettext is defined as a macro. So include
+ it now, to make later inclusions of <libintl.h> a NOP. */
+#if defined(__cplusplus) && defined(__GNUG__) && (__GNUC__ >= 3)
+# include <cstdlib>
+# if (__GLIBC__ >= 2 && !defined __UCLIBC__) || _GLIBCXX_HAVE_LIBINTL_H
+# include <libintl.h>
+# endif
+#endif
+
+/* Disabled NLS.
+ The casts to 'const char *' serve the purpose of producing warnings
+ for invalid uses of the value returned from these functions.
+ On pre-ANSI systems without 'const', the config.h file is supposed to
+ contain "#define const". */
+# undef gettext
+# define gettext(Msgid) ((const char *) (Msgid))
+# undef dgettext
+# define dgettext(Domainname, Msgid) ((void) (Domainname), gettext (Msgid))
+# undef dcgettext
+# define dcgettext(Domainname, Msgid, Category) \
+ ((void) (Category), dgettext (Domainname, Msgid))
+# undef ngettext
+# define ngettext(Msgid1, Msgid2, N) \
+ ((N) == 1 \
+ ? ((void) (Msgid2), (const char *) (Msgid1)) \
+ : ((void) (Msgid1), (const char *) (Msgid2)))
+# undef dngettext
+# define dngettext(Domainname, Msgid1, Msgid2, N) \
+ ((void) (Domainname), ngettext (Msgid1, Msgid2, N))
+# undef dcngettext
+# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \
+ ((void) (Category), dngettext (Domainname, Msgid1, Msgid2, N))
+# undef textdomain
+# define textdomain(Domainname) ((const char *) (Domainname))
+# undef bindtextdomain
+# define bindtextdomain(Domainname, Dirname) \
+ ((void) (Domainname), (const char *) (Dirname))
+# undef bind_textdomain_codeset
+# define bind_textdomain_codeset(Domainname, Codeset) \
+ ((void) (Domainname), (const char *) (Codeset))
+
+#endif
+
+/* Prefer gnulib's setlocale override over libintl's setlocale override. */
+#ifdef GNULIB_defined_setlocale
+# undef setlocale
+# define setlocale rpl_setlocale
+#endif
+
+/* A pseudo function call that serves as a marker for the automated
+ extraction of messages, but does not call gettext(). The run-time
+ translation is done at a different place in the code.
+ The argument, String, should be a literal string. Concatenated strings
+ and other string expressions won't work.
+ The macro's expansion is not parenthesized, so that it is suitable as
+ initializer for static 'char[]' or 'const char[]' variables. */
+#define gettext_noop(String) String
+
+/* The separator between msgctxt and msgid in a .mo file. */
+#define GETTEXT_CONTEXT_GLUE "\004"
+
+/* Pseudo function calls, taking a MSGCTXT and a MSGID instead of just a
+ MSGID. MSGCTXT and MSGID must be string literals. MSGCTXT should be
+ short and rarely need to change.
+ The letter 'p' stands for 'particular' or 'special'. */
+#ifdef DEFAULT_TEXT_DOMAIN
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#else
+# define pgettext(Msgctxt, Msgid) \
+ pgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#endif
+#define dpgettext(Domainname, Msgctxt, Msgid) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, LC_MESSAGES)
+#define dcpgettext(Domainname, Msgctxt, Msgid, Category) \
+ pgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, Category)
+#ifdef DEFAULT_TEXT_DOMAIN
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (DEFAULT_TEXT_DOMAIN, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#else
+# define npgettext(Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (NULL, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#endif
+#define dnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dcnpgettext(Domainname, Msgctxt, Msgid, MsgidPlural, N, Category) \
+ npgettext_aux (Domainname, Msgctxt GETTEXT_CONTEXT_GLUE Msgid, Msgid, MsgidPlural, N, Category)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+pgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ int category)
+{
+ const char *translation = dcgettext (domain, msg_ctxt_id, category);
+ if (translation == msg_ctxt_id)
+ return msgid;
+ else
+ return translation;
+}
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+npgettext_aux (const char *domain,
+ const char *msg_ctxt_id, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ const char *translation =
+ dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+ if (translation == msg_ctxt_id || translation == msgid_plural)
+ return (n == 1 ? msgid : msgid_plural);
+ else
+ return translation;
+}
+
+/* The same thing extended for non-constant arguments. Here MSGCTXT and MSGID
+ can be arbitrary expressions. But for string literals these macros are
+ less efficient than those above. */
+
+#include <string.h>
+
+#if (((__GNUC__ >= 3 || __GNUG__ >= 2) && !defined __STRICT_ANSI__) \
+ /* || __STDC_VERSION__ >= 199901L */ )
+# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 1
+#else
+# define _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS 0
+#endif
+
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+#include <stdlib.h>
+#endif
+
+#define pgettext_expr(Msgctxt, Msgid) \
+ dcpgettext_expr (NULL, Msgctxt, Msgid, LC_MESSAGES)
+#define dpgettext_expr(Domainname, Msgctxt, Msgid) \
+ dcpgettext_expr (Domainname, Msgctxt, Msgid, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcgettext (domain, msg_ctxt_id, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (translation != msg_ctxt_id)
+ return translation;
+ }
+ return msgid;
+}
+
+#define npgettext_expr(Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (NULL, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+#define dnpgettext_expr(Domainname, Msgctxt, Msgid, MsgidPlural, N) \
+ dcnpgettext_expr (Domainname, Msgctxt, Msgid, MsgidPlural, N, LC_MESSAGES)
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static const char *
+dcnpgettext_expr (const char *domain,
+ const char *msgctxt, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
+{
+ size_t msgctxt_len = strlen (msgctxt) + 1;
+ size_t msgid_len = strlen (msgid) + 1;
+ const char *translation;
+#if _LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ char msg_ctxt_id[msgctxt_len + msgid_len];
+#else
+ char buf[1024];
+ char *msg_ctxt_id =
+ (msgctxt_len + msgid_len <= sizeof (buf)
+ ? buf
+ : (char *) malloc (msgctxt_len + msgid_len));
+ if (msg_ctxt_id != NULL)
+#endif
+ {
+ memcpy (msg_ctxt_id, msgctxt, msgctxt_len - 1);
+ msg_ctxt_id[msgctxt_len - 1] = '\004';
+ memcpy (msg_ctxt_id + msgctxt_len, msgid, msgid_len);
+ translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
+#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
+ if (msg_ctxt_id != buf)
+ free (msg_ctxt_id);
+#endif
+ if (!(translation == msg_ctxt_id || translation == msgid_plural))
+ return translation;
+ }
+ return (n == 1 ? msgid : msgid_plural);
+}
+
+#endif /* _LIBGETTEXT_H */
--- /dev/null
+/*
+ ptouch-print - Print labels with images or text on a Brother P-Touch
+
+ Copyright (C) 2015 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 3 as
+ published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdint.h>
+#include <libusb-1.0/libusb.h>
+
+struct _pt_tape_info {
+ uint8_t mm; /* Tape width in mm */
+ uint8_t px; /* Printing area in px */
+};
+
+struct _pt_dev_info {
+ int vid; /* USB vendor ID */
+ int pid; /* USB product ID */
+ char *name;
+ int max_px; /* Maximum pixel width that can be printed */
+ int flags;
+};
+typedef struct _pt_dev_info *pt_dev_info;
+
+struct _ptouch_dev {
+ libusb_device_handle *h;
+ uint8_t raw[32];
+ uint8_t tape_width_mm;
+ uint8_t tape_width_px;
+ uint8_t status;
+ uint8_t media_type;
+ pt_dev_info devinfo;
+};
+typedef struct _ptouch_dev *ptouch_dev;
+
+int ptouch_open(ptouch_dev *ptdev);
+int ptouch_close(ptouch_dev ptdev);
+int ptouch_send(ptouch_dev ptdev, uint8_t *data, int len);
+int ptouch_init(ptouch_dev ptdev);
+int ptouch_lf(ptouch_dev ptdev);
+int ptouch_ff(ptouch_dev ptdev);
+int ptouch_cutmark(ptouch_dev ptdev);
+int ptouch_eject(ptouch_dev ptdev);
+int ptouch_getstatus(ptouch_dev ptdev);
+int ptouch_getmaxwidth(ptouch_dev ptdev);
+int ptouch_rasterstart(ptouch_dev ptdev);
+int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, int len);
--- /dev/null
+# available languages
+de
+en
--- /dev/null
+# List of source files which contain translatable strings.
+src/libptouch.c
+src/ptouch-print.c
--- /dev/null
+# German translations for ptouch-print package
+# German translation for ptouch-print.
+# Copyright (C) 2015 Free Software Foundation, Inc.
+# This file is distributed under the same license as the ptouch-print package.
+# <dominic.radermacher@gmail.com>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ptouch-print 1.3.1\n"
+"Report-Msgid-Bugs-To: dominic.radermacher@gmail.com\n"
+"POT-Creation-Date: 2015-11-12 21:33+0100\n"
+"PO-Revision-Date: 2015-11-11 09:35+0100\n"
+"Last-Translator: <dominic.radermacher@gmail.com>\n"
+"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/libptouch.c:59
+#, c-format
+msgid "out of memory\n"
+msgstr "Nicht genug Speicher\n"
+
+#: src/libptouch.c:63
+#, c-format
+msgid "libusb_init() failed\n"
+msgstr "ptouch_init() fehlgeschlagen\n"
+
+#: src/libptouch.c:72
+#, c-format
+msgid "failed to get device descriptor"
+msgstr ""
+
+#: src/libptouch.c:78
+#, c-format
+msgid "%s found on USB bus %d, device %d\n"
+msgstr "Drucker %s am USB Bus %d, Gerät %d gefunden\n"
+
+#: src/libptouch.c:83
+#, c-format
+msgid "libusb_open error :%s\n"
+msgstr ""
+
+#: src/libptouch.c:89
+#, c-format
+msgid "error while detaching kernel driver: %s\n"
+msgstr ""
+
+#: src/libptouch.c:93
+#, c-format
+msgid "interface claim error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:101
+#, c-format
+msgid ""
+"No P-Touch printer found on USB (remember to put switch to position E)\n"
+msgstr "Kein P-Ptouch Drucker am USB gefunden (Schalter muss auf E stehen)\n"
+
+#: src/libptouch.c:121
+#, c-format
+msgid "write error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:125
+#, c-format
+msgid "write error: could send only %i of %i bytes\n"
+msgstr ""
+
+#: src/libptouch.c:194
+#, c-format
+msgid "debug: dumping raw status bytes\n"
+msgstr ""
+
+#: src/libptouch.c:218 src/libptouch.c:263
+#, c-format
+msgid "read error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:223
+#, c-format
+msgid "timeout while waiting for status response\n"
+msgstr ""
+
+#: src/libptouch.c:231
+#, c-format
+msgid "Error 1 = %02x\n"
+msgstr "Fehlerbyte1 = %02x\n"
+
+#: src/libptouch.c:234
+#, c-format
+msgid "Error 2 = %02x\n"
+msgstr "Fehlerbyte2 = %02x\n"
+
+#: src/libptouch.c:244
+#, c-format
+msgid "unknown tape width of %imm, please report this.\n"
+msgstr "Unbekannte Schriftband breite (%i mm), bitte melden\n"
+
+#: src/libptouch.c:252
+#, c-format
+msgid "got only 16 bytes... wondering what they are:\n"
+msgstr "nur 16 bytes empfangen... mal gucken was die sind:\n"
+
+#: src/libptouch.c:256
+#, c-format
+msgid "read error: got %i instead of 32 bytes\n"
+msgstr "Lesefehler: %i anstatt 32 bytes empfangen\n"
+
+#: src/libptouch.c:259
+#, c-format
+msgid "strange status:\n"
+msgstr "Seltsamer Status:\n"
+
+#: src/libptouch.c:261
+#, c-format
+msgid "trying to flush junk\n"
+msgstr ""
+
+#: src/libptouch.c:266
+#, c-format
+msgid "got another %i bytes. now try again\n"
+msgstr "weitere %i bytes empfangen. probiere es nochmal.\n"
+
+#: src/ptouch-print.c:71
+#, c-format
+msgid "image is too large (%ipx x %ipx)\n"
+msgstr "Bild ist zu gross (%ipx x %ipx)\n"
+
+#: src/ptouch-print.c:72 src/ptouch-print.c:356
+#, c-format
+msgid "maximum printing width for this tape is %ipx\n"
+msgstr "Maximal druckbare Breite für dieses Schriftband sind %ipx\n"
+
+#: src/ptouch-print.c:77
+#, c-format
+msgid "ptouch_rasterstart() failed\n"
+msgstr "ptouch_rasterstart() fehlgeschlagen\n"
+
+#: src/ptouch-print.c:88
+#, c-format
+msgid "ptouch_send() failed\n"
+msgstr "ptouch_send() fehlgeschlagen\n"
+
+#: src/ptouch-print.c:128
+#, c-format
+msgid "writing image '%s' failed\n"
+msgstr "Schreiben der Bilddatei '%s' fehlgeschlagen\n"
+
+#: src/ptouch-print.c:197
+#, c-format
+msgid "warning: font config not available\n"
+msgstr "Warnung: fontconfig ist nicht verfügbar\n"
+
+#: src/ptouch-print.c:201
+#, c-format
+msgid "setting font size=%i\n"
+msgstr "setze Zeichensatzgrösse=%i\n"
+
+#: src/ptouch-print.c:205
+#, c-format
+msgid "could not estimate needed font size\n"
+msgstr "Konnte die notwendige Zeichensatzgrösse nicht bestimmen\n"
+
+#: src/ptouch-print.c:212
+#, c-format
+msgid "choosing font size=%i\n"
+msgstr "Wähle Zeichensatzgrösse %i\n"
+
+#: src/ptouch-print.c:226 src/ptouch-print.c:232
+#, c-format
+msgid "error in gdImageStringFT: %s\n"
+msgstr "Fehler in Funktion gdImageStringFT(): %s\n"
+
+#: src/ptouch-print.c:299
+#, c-format
+msgid "ptouch-print version %s by Dominic Radermacher\n"
+msgstr "ptouch-print Version %s von Dominic Radermacher\n"
+
+#: src/ptouch-print.c:326
+#, c-format
+msgid "ptouch_init() failed\n"
+msgstr "ptouch_init() fehlgeschlagen\n"
+
+#: src/ptouch-print.c:329
+#, c-format
+msgid "ptouch_getstatus() failed\n"
+msgstr "ptouch_getstatus() fehlgeschlagen\n"
+
+#: src/ptouch-print.c:373
+#, c-format
+msgid "could not render text\n"
+msgstr "Konnte Text nicht rendern\n"
+
+#: src/ptouch-print.c:389
+#, c-format
+msgid "ptouch_eject() failed\n"
+msgstr "ptouch_eject() fehlgeschlagen\n"
--- /dev/null
+# English translations for ptouch-print package.
+# Copyright (C) 2015 Free Software Foundation, Inc.
+# This file is distributed under the same license as the ptouch-print package.
+# <dominic.radermacher@gmail.com>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ptouch-print 1.3.1\n"
+"Report-Msgid-Bugs-To: dominic.radermacher@gmail.com\n"
+"POT-Creation-Date: 2015-11-12 21:33+0100\n"
+"PO-Revision-Date: 2015-11-11 09:47+0100\n"
+"Last-Translator: <dominic.radermacher@gmail.com>\n"
+"Language-Team: English <en@translate.freefriends.org>\n"
+"Language: en\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/libptouch.c:59
+#, c-format
+msgid "out of memory\n"
+msgstr "out of memory\n"
+
+#: src/libptouch.c:63
+#, c-format
+msgid "libusb_init() failed\n"
+msgstr "libusb_init() failed\n"
+
+#: src/libptouch.c:72
+#, c-format
+msgid "failed to get device descriptor"
+msgstr "failed to get device descriptor"
+
+#: src/libptouch.c:78
+#, c-format
+msgid "%s found on USB bus %d, device %d\n"
+msgstr "%s found on USB bus %d, device %d\n"
+
+#: src/libptouch.c:83
+#, c-format
+msgid "libusb_open error :%s\n"
+msgstr "libusb_open error :%s\n"
+
+#: src/libptouch.c:89
+#, c-format
+msgid "error while detaching kernel driver: %s\n"
+msgstr "error while detaching kernel driver: %s\n"
+
+#: src/libptouch.c:93
+#, c-format
+msgid "interface claim error: %s\n"
+msgstr "interface claim error: %s\n"
+
+#: src/libptouch.c:101
+#, c-format
+msgid ""
+"No P-Touch printer found on USB (remember to put switch to position E)\n"
+msgstr ""
+"No P-Touch printer found on USB (remember to put switch to position E)\n"
+
+#: src/libptouch.c:121
+#, c-format
+msgid "write error: %s\n"
+msgstr "write error: %s\n"
+
+#: src/libptouch.c:125
+#, c-format
+msgid "write error: could send only %i of %i bytes\n"
+msgstr "write error: could send only %i of %i bytes\n"
+
+#: src/libptouch.c:194
+#, c-format
+msgid "debug: dumping raw status bytes\n"
+msgstr "debug: dumping raw status bytes\n"
+
+#: src/libptouch.c:218 src/libptouch.c:263
+#, c-format
+msgid "read error: %s\n"
+msgstr "read error: %s\n"
+
+#: src/libptouch.c:223
+#, c-format
+msgid "timeout while waiting for status response\n"
+msgstr "timeout while waiting for status response\n"
+
+#: src/libptouch.c:231
+#, c-format
+msgid "Error 1 = %02x\n"
+msgstr "Error 1 = %02x\n"
+
+#: src/libptouch.c:234
+#, c-format
+msgid "Error 2 = %02x\n"
+msgstr "Error 2 = %02x\n"
+
+#: src/libptouch.c:244
+#, c-format
+msgid "unknown tape width of %imm, please report this.\n"
+msgstr "unknown tape width of %imm, please report this.\n"
+
+#: src/libptouch.c:252
+#, c-format
+msgid "got only 16 bytes... wondering what they are:\n"
+msgstr "got only 16 bytes... wondering what they are:\n"
+
+#: src/libptouch.c:256
+#, c-format
+msgid "read error: got %i instead of 32 bytes\n"
+msgstr "read error: got %i instead of 32 bytes\n"
+
+#: src/libptouch.c:259
+#, c-format
+msgid "strange status:\n"
+msgstr "strange status:\n"
+
+#: src/libptouch.c:261
+#, c-format
+msgid "trying to flush junk\n"
+msgstr "trying to flush junk\n"
+
+#: src/libptouch.c:266
+#, c-format
+msgid "got another %i bytes. now try again\n"
+msgstr "got another %i bytes. now try again\n"
+
+#: src/ptouch-print.c:71
+#, c-format
+msgid "image is too large (%ipx x %ipx)\n"
+msgstr "image is too large (%ipx x %ipx)\n"
+
+#: src/ptouch-print.c:72 src/ptouch-print.c:356
+#, c-format
+msgid "maximum printing width for this tape is %ipx\n"
+msgstr "maximum printing width for this tape is %ipx\n"
+
+#: src/ptouch-print.c:77
+#, c-format
+msgid "ptouch_rasterstart() failed\n"
+msgstr "ptouch_rasterstart() failed\n"
+
+#: src/ptouch-print.c:88
+#, c-format
+msgid "ptouch_send() failed\n"
+msgstr "ptouch_send() failed\n"
+
+#: src/ptouch-print.c:128
+#, c-format
+msgid "writing image '%s' failed\n"
+msgstr "writing image '%s' failed\n"
+
+#: src/ptouch-print.c:197
+#, c-format
+msgid "warning: font config not available\n"
+msgstr "warning: font config not available\n"
+
+#: src/ptouch-print.c:201
+#, c-format
+msgid "setting font size=%i\n"
+msgstr "setting font size=%i\n"
+
+#: src/ptouch-print.c:205
+#, c-format
+msgid "could not estimate needed font size\n"
+msgstr "could not estimate needed font size\n"
+
+#: src/ptouch-print.c:212
+#, c-format
+msgid "choosing font size=%i\n"
+msgstr "choosing font size=%i\n"
+
+#: src/ptouch-print.c:226 src/ptouch-print.c:232
+#, c-format
+msgid "error in gdImageStringFT: %s\n"
+msgstr "error in gdImageStringFT: %s\n"
+
+#: src/ptouch-print.c:299
+#, c-format
+msgid "ptouch-print version %s by Dominic Radermacher\n"
+msgstr "ptouch-print version %s by Dominic Radermacher\n"
+
+#: src/ptouch-print.c:326
+#, c-format
+msgid "ptouch_init() failed\n"
+msgstr "ptouch_init() failed\n"
+
+#: src/ptouch-print.c:329
+#, c-format
+msgid "ptouch_getstatus() failed\n"
+msgstr "ptouch_getstatus() failed\n"
+
+#: src/ptouch-print.c:373
+#, c-format
+msgid "could not render text\n"
+msgstr "could not render text\n"
+
+#: src/ptouch-print.c:389
+#, c-format
+msgid "ptouch_eject() failed\n"
+msgstr "ptouch_eject() failed\n"
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# This file is distributed under the same license as the ptouch package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: ptouch 1.3.1\n"
+"Report-Msgid-Bugs-To: dominic.radermacher@gmail.com\n"
+"POT-Creation-Date: 2015-11-12 21:33+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/libptouch.c:59
+#, c-format
+msgid "out of memory\n"
+msgstr ""
+
+#: src/libptouch.c:63
+#, c-format
+msgid "libusb_init() failed\n"
+msgstr ""
+
+#: src/libptouch.c:72
+#, c-format
+msgid "failed to get device descriptor"
+msgstr ""
+
+#: src/libptouch.c:78
+#, c-format
+msgid "%s found on USB bus %d, device %d\n"
+msgstr ""
+
+#: src/libptouch.c:83
+#, c-format
+msgid "libusb_open error :%s\n"
+msgstr ""
+
+#: src/libptouch.c:89
+#, c-format
+msgid "error while detaching kernel driver: %s\n"
+msgstr ""
+
+#: src/libptouch.c:93
+#, c-format
+msgid "interface claim error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:101
+#, c-format
+msgid ""
+"No P-Touch printer found on USB (remember to put switch to position E)\n"
+msgstr ""
+
+#: src/libptouch.c:121
+#, c-format
+msgid "write error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:125
+#, c-format
+msgid "write error: could send only %i of %i bytes\n"
+msgstr ""
+
+#: src/libptouch.c:194
+#, c-format
+msgid "debug: dumping raw status bytes\n"
+msgstr ""
+
+#: src/libptouch.c:218 src/libptouch.c:263
+#, c-format
+msgid "read error: %s\n"
+msgstr ""
+
+#: src/libptouch.c:223
+#, c-format
+msgid "timeout while waiting for status response\n"
+msgstr ""
+
+#: src/libptouch.c:231
+#, c-format
+msgid "Error 1 = %02x\n"
+msgstr ""
+
+#: src/libptouch.c:234
+#, c-format
+msgid "Error 2 = %02x\n"
+msgstr ""
+
+#: src/libptouch.c:244
+#, c-format
+msgid "unknown tape width of %imm, please report this.\n"
+msgstr ""
+
+#: src/libptouch.c:252
+#, c-format
+msgid "got only 16 bytes... wondering what they are:\n"
+msgstr ""
+
+#: src/libptouch.c:256
+#, c-format
+msgid "read error: got %i instead of 32 bytes\n"
+msgstr ""
+
+#: src/libptouch.c:259
+#, c-format
+msgid "strange status:\n"
+msgstr ""
+
+#: src/libptouch.c:261
+#, c-format
+msgid "trying to flush junk\n"
+msgstr ""
+
+#: src/libptouch.c:266
+#, c-format
+msgid "got another %i bytes. now try again\n"
+msgstr ""
+
+#: src/ptouch-print.c:71
+#, c-format
+msgid "image is too large (%ipx x %ipx)\n"
+msgstr ""
+
+#: src/ptouch-print.c:72 src/ptouch-print.c:356
+#, c-format
+msgid "maximum printing width for this tape is %ipx\n"
+msgstr ""
+
+#: src/ptouch-print.c:77
+#, c-format
+msgid "ptouch_rasterstart() failed\n"
+msgstr ""
+
+#: src/ptouch-print.c:88
+#, c-format
+msgid "ptouch_send() failed\n"
+msgstr ""
+
+#: src/ptouch-print.c:128
+#, c-format
+msgid "writing image '%s' failed\n"
+msgstr ""
+
+#: src/ptouch-print.c:197
+#, c-format
+msgid "warning: font config not available\n"
+msgstr ""
+
+#: src/ptouch-print.c:201
+#, c-format
+msgid "setting font size=%i\n"
+msgstr ""
+
+#: src/ptouch-print.c:205
+#, c-format
+msgid "could not estimate needed font size\n"
+msgstr ""
+
+#: src/ptouch-print.c:212
+#, c-format
+msgid "choosing font size=%i\n"
+msgstr ""
+
+#: src/ptouch-print.c:226 src/ptouch-print.c:232
+#, c-format
+msgid "error in gdImageStringFT: %s\n"
+msgstr ""
+
+#: src/ptouch-print.c:299
+#, c-format
+msgid "ptouch-print version %s by Dominic Radermacher\n"
+msgstr ""
+
+#: src/ptouch-print.c:326
+#, c-format
+msgid "ptouch_init() failed\n"
+msgstr ""
+
+#: src/ptouch-print.c:329
+#, c-format
+msgid "ptouch_getstatus() failed\n"
+msgstr ""
+
+#: src/ptouch-print.c:373
+#, c-format
+msgid "could not render text\n"
+msgstr ""
+
+#: src/ptouch-print.c:389
+#, c-format
+msgid "ptouch_eject() failed\n"
+msgstr ""
--- /dev/null
+/*
+ libptouch - functions to help accessing a brother ptouch
+
+ Copyright (C) 2013 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 3 as
+ published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <stdlib.h> /* malloc() */
+#include <string.h> /* memcmp() */
+#include <sys/types.h> /* open() */
+#include <sys/stat.h> /* open() */
+#include <fcntl.h> /* open() */
+#include <time.h> /* nanosleep(), struct timespec */
+#include "config.h"
+#include "gettext.h" /* gettext(), ngettext() */
+#include "ptouch.h"
+
+#define _(s) gettext(s)
+
+struct _pt_tape_info tape_info[5]= {
+ {9, 52}, /* 9mm tape is 52px wide? works for me ;-) */
+ {12,76}, /* and 76px work for me on a 12mm tape - maybe its only 64px */
+ {18,120},
+ {24,128},
+ {0,0} /* terminating entry */
+};
+
+struct _pt_dev_info ptdevs[] = {
+ {0x04f9, 0x202d, "PT-2430PC", 128, 0}, /* 180dpi, maximum 128px */
+ {0x04f9, 0x202c, "PT-1230PC", 76, 0}, /* 180dpi, supports tapes up to 12mm - I don't know how much pixels it can print! */
+ {0,0,"",0,0}
+};
+
+void ptouch_rawstatus(uint8_t raw[32]);
+
+int ptouch_open(ptouch_dev *ptdev)
+{
+ libusb_device **devs;
+ libusb_device *dev;
+ libusb_device_handle *handle = NULL;
+ struct libusb_device_descriptor desc;
+ ssize_t cnt;
+ int r,i=0;
+
+ if ((*ptdev=malloc(sizeof(struct _ptouch_dev))) == NULL) {
+ fprintf(stderr, _("out of memory\n"));
+ return -1;
+ }
+ if ((libusb_init(NULL)) < 0) {
+ fprintf(stderr, _("libusb_init() failed\n"));
+ return -1;
+ }
+// libusb_set_debug(NULL, 3);
+ if ((cnt=libusb_get_device_list(NULL, &devs)) < 0) {
+ return -1;
+ }
+ while ((dev=devs[i++]) != NULL) {
+ if ((r=libusb_get_device_descriptor(dev, &desc)) < 0) {
+ fprintf(stderr, _("failed to get device descriptor"));
+ libusb_free_device_list(devs, 1);
+ return -1;
+ }
+ for (int k=0; ptdevs[k].vid > 0; k++) {
+ if ((desc.idVendor == ptdevs[k].vid) && (desc.idProduct == ptdevs[k].pid) && (ptdevs[k].flags >= 0)) {
+ fprintf(stderr, _("%s found on USB bus %d, device %d\n"),
+ ptdevs[k].name,
+ libusb_get_bus_number(dev),
+ libusb_get_device_address(dev));
+ if ((r=libusb_open(dev, &handle)) != 0) {
+ fprintf(stderr, _("libusb_open error :%s\n"), libusb_error_name(r));
+ return -1;
+ }
+ libusb_free_device_list(devs, 1);
+ if ((r=libusb_kernel_driver_active(handle, 0)) == 1) {
+ if ((r=libusb_detach_kernel_driver(handle, 0)) != 0) {
+ fprintf(stderr, _("error while detaching kernel driver: %s\n"), libusb_error_name(r));
+ }
+ }
+ if ((r=libusb_claim_interface(handle, 0)) != 0) {
+ fprintf(stderr, _("interface claim error: %s\n"), libusb_error_name(r));
+ return -1;
+ }
+ (*ptdev)->h=handle;
+ return 0;
+ }
+ }
+ }
+ fprintf(stderr, _("No P-Touch printer found on USB (remember to put switch to position E)\n"));
+ libusb_free_device_list(devs, 1);
+ return -1;
+}
+
+int ptouch_close(ptouch_dev ptdev)
+{
+ libusb_release_interface(ptdev->h, 0);
+ libusb_close(ptdev->h);
+ return 0;
+}
+
+int ptouch_send(ptouch_dev ptdev, uint8_t *data, int len)
+{
+ int r,tx;
+
+ if (ptdev == NULL) {
+ return -1;
+ }
+ if ((r=libusb_bulk_transfer(ptdev->h, 0x02, data, len, &tx, 0)) != 0) {
+ fprintf(stderr, _("write error: %s\n"), libusb_error_name(r));
+ return -1;
+ }
+ if (tx != len) {
+ fprintf(stderr, _("write error: could send only %i of %i bytes\n"), tx, len);
+ return -1;
+ }
+ return 0;
+}
+
+int ptouch_init(ptouch_dev ptdev)
+{
+ char cmd[]="\x1b\x40"; /* 1B 40 = ESC @ = INIT */
+ return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+}
+
+int ptouch_rasterstart(ptouch_dev ptdev)
+{
+ char cmd[]="\x1b\x69\x52\x01"; /* 1B 69 52 01 = RASTER DATA */
+ return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+}
+
+/* print an empty line */
+int ptouch_lf(ptouch_dev ptdev)
+{
+ char cmd[]="\x5a";
+ return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+}
+
+/* print and advance tape, but do not cut */
+int ptouch_ff(ptouch_dev ptdev)
+{
+ char cmd[]="\x0c";
+ return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+}
+
+/* print and cut tape */
+int ptouch_eject(ptouch_dev ptdev)
+{
+ char cmd[]="\x1a";
+ return ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+}
+
+/* print a "cut here" mark (it's just a dashed line) */
+#define CUTMARK_SPACING 5
+int ptouch_cutmark(ptouch_dev ptdev)
+{
+ uint8_t buf[32];
+ int i,len=16;
+
+ for (i=0; i<CUTMARK_SPACING; i++) {
+ ptouch_lf(ptdev);
+ }
+ ptouch_rasterstart(ptdev);
+ buf[0]=0x47;
+ buf[1]=len;
+ buf[2]=0;
+ memset(buf+3, 0, len);
+ int offset=(64-ptouch_getmaxwidth(ptdev)/2);
+ for (i=0; i<ptouch_getmaxwidth(ptdev); i++) {
+ if ((i%8) <= 3) { /* pixels 0-3 get set, 4-7 are unset */
+ buf[3+15-((offset+i)/8)] |= 1<<((offset+i)%8);
+ }
+ }
+ ptouch_send(ptdev, buf, len+3);
+ for (i=0; i<CUTMARK_SPACING; i++) {
+ ptouch_lf(ptdev);
+ }
+ return 0;
+}
+
+void ptouch_rawstatus(uint8_t raw[32])
+{
+ fprintf(stderr, _("debug: dumping raw status bytes\n"));
+ for (int i=0; i<32; i++) {
+ fprintf(stderr, "%02x ", raw[i]);
+ if (((i+1) % 16) == 0) {
+ fprintf(stderr, "\n");
+ }
+ }
+ fprintf(stderr, "\n");
+ return;
+}
+
+int ptouch_getstatus(ptouch_dev ptdev)
+{
+ char cmd[]="\x1b\x69\x53";
+ uint8_t buf[32];
+ int i, r, tx=0, tries=0;
+ struct timespec w;
+
+ ptouch_send(ptdev, (uint8_t *)cmd, strlen(cmd));
+ while (tx == 0) {
+ w.tv_sec=0;
+ w.tv_nsec=100000000; /* 0.1 sec */
+ r=nanosleep(&w, NULL);
+ if ((r=libusb_bulk_transfer(ptdev->h, 0x81, buf, 32, &tx, 0)) != 0) {
+ fprintf(stderr, _("read error: %s\n"), libusb_error_name(r));
+ return -1;
+ }
+ tries++;
+ if (tries > 10) {
+ fprintf(stderr, _("timeout while waiting for status response\n"));
+ return -1;
+ }
+ }
+ if (tx == 32) {
+ if (buf[0]==0x80 && buf[1]==0x20) {
+ memcpy(ptdev->raw, buf, 32);
+ if (buf[8] != 0) {
+ fprintf(stderr, _("Error 1 = %02x\n"), buf[8]);
+ }
+ if (buf[9] != 0) {
+ fprintf(stderr, _("Error 2 = %02x\n"), buf[9]);
+ }
+ ptdev->tape_width_mm=buf[10];
+ ptdev->tape_width_px=0;
+ for (i=0; tape_info[i].mm > 0; i++) {
+ if (tape_info[i].mm == buf[10]) {
+ ptdev->tape_width_px=tape_info[i].px;
+ }
+ }
+ if (ptdev->tape_width_px == 0) {
+ fprintf(stderr, _("unknown tape width of %imm, please report this.\n"), buf[10]);
+ }
+ ptdev->media_type=buf[11];
+ ptdev->status=buf[18];
+ return 0;
+ }
+ }
+ if (tx == 16) {
+ fprintf(stderr, _("got only 16 bytes... wondering what they are:\n"));
+ ptouch_rawstatus(buf);
+ }
+ if (tx != 32) {
+ fprintf(stderr, _("read error: got %i instead of 32 bytes\n"), tx);
+ return -1;
+ }
+ fprintf(stderr, _("strange status:\n"));
+ ptouch_rawstatus(buf);
+ fprintf(stderr, _("trying to flush junk\n"));
+ if ((r=libusb_bulk_transfer(ptdev->h, 0x81, buf, 32, &tx, 0)) != 0) {
+ fprintf(stderr, _("read error: %s\n"), libusb_error_name(r));
+ return -1;
+ }
+ fprintf(stderr, _("got another %i bytes. now try again\n"), tx);
+ return -1;
+}
+
+int ptouch_getmaxwidth(ptouch_dev ptdev)
+{
+ return ptdev->tape_width_px;
+}
+
+int ptouch_sendraster(ptouch_dev ptdev, uint8_t *data, int len)
+{
+ uint8_t buf[32];
+
+ if (len > 16) { /* PT-2430PC can not print more than 128 px */
+ return -1; /* as we support more devices, we need to check */
+ } /* how much pixels each device support */
+ buf[0]=0x47;
+ buf[1]=len;
+ buf[2]=0;
+ memcpy(buf+3, data, len);
+ return ptouch_send(ptdev, buf, len+3);
+}
--- /dev/null
+/*
+ ptouch-gtk - Simple GTK+ UI to print labels on a Brother P-Touch
+
+ Copyright (C) 2015 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 3 as
+ published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <gtk/gtk.h>
+
+#define BUILDER_XML_FILE "data/ptouch.ui"
+
+typedef struct
+{
+ GtkWidget *window;
+ GtkWidget *statusbar;
+ GtkWidget *text_view;
+ guint statusbar_context_id;
+} PTouchEditor;
+
+/* prototypes */
+void error_message(const gchar *message);
+void on_window_destroy(GtkWidget *object, PTouchEditor *editor);
+gboolean on_window_delete_event(GtkWidget *widget, GdkEvent *event,
+ PTouchEditor *editor);
+gboolean init_app(PTouchEditor *editor);
+
+void error_message(const gchar *message)
+{
+ GtkWidget *dialog;
+ g_warning(message); /* log to terminal window */
+ /* create an error message dialog and display modally to the user */
+ dialog = gtk_message_dialog_new(NULL,
+ GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, message);
+ gtk_window_set_title(GTK_WINDOW(dialog), "Error!");
+ gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+}
+
+void on_window_destroy(GtkWidget *object, PTouchEditor *editor)
+{
+ gtk_main_quit();
+}
+
+gboolean on_window_delete_event(GtkWidget *widget, GdkEvent *event, PTouchEditor *editor)
+{
+ return FALSE; /* propogate event */
+}
+
+void show_about(PTouchEditor *editor)
+{
+ static const gchar * const authors[] = {
+ "Dominic Radermacher <dominic.radermacher@gmail.com>",
+ NULL
+ };
+ static const gchar copyright[] = "Copyright \xc2\xa9 2015 Dominic Radermacher";
+ static const gchar comments[] = "PTouch Print";
+
+ gtk_show_about_dialog(GTK_WINDOW(editor->window), "authors", authors,
+ "comments", comments, "copyright", copyright,
+ "version", "0.1",
+ "website", "http://mockmoon-cybernetics.ch/",
+ "program-name", "ptouch-gtk",
+ "logo-icon-name", GTK_STOCK_EDIT, NULL);
+}
+
+gboolean init_app(PTouchEditor *editor)
+{
+ GtkBuilder *builder;
+ GError *err=NULL;
+ guint id;
+
+ /* use GtkBuilder to build our interface from the XML file */
+ builder = gtk_builder_new();
+ if (gtk_builder_add_from_file(builder, BUILDER_XML_FILE, &err) == 0) {
+ error_message(err->message);
+ g_error_free(err);
+ return FALSE;
+ }
+ /* get the widgets which will be referenced in callbacks */
+ editor->window = GTK_WIDGET(gtk_builder_get_object(builder, "window"));
+ editor->statusbar = GTK_WIDGET(gtk_builder_get_object(builder, "statusbar"));
+ editor->text_view = GTK_WIDGET(gtk_builder_get_object(builder, "text_view"));
+ gtk_builder_connect_signals(builder, editor);
+ /* free memory used by GtkBuilder object */
+ g_object_unref(G_OBJECT(builder));
+ gtk_window_set_default_icon_name(GTK_STOCK_EDIT);
+ /* setup and initialize our statusbar */
+ id = gtk_statusbar_get_context_id(GTK_STATUSBAR(editor->statusbar),
+ "PTouch Print GTK+");
+ editor->statusbar_context_id = id;
+ return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+ PTouchEditor *editor;
+
+ editor = g_slice_new(PTouchEditor);
+ gtk_init(&argc, &argv);
+ if (init_app(editor) == FALSE) {
+ return 1; /* error loading UI */
+ }
+ gtk_widget_show(editor->window);
+ gtk_main();
+ g_slice_free(PTouchEditor, editor);
+}
--- /dev/null
+/*
+ ptouch-print - Print labels with images or text on a Brother P-Touch
+
+ Copyright (C) 2015 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License version 3 as
+ published by the Free Software Foundation
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h> /* printf() */
+#include <stdlib.h> /* exit(), malloc() */
+#include <string.h> /* strcmp(), memcmp() */
+#include <sys/types.h> /* open() */
+#include <sys/stat.h> /* open() */
+#include <fcntl.h> /* open() */
+#include <gd.h>
+#include "config.h"
+#include "gettext.h" /* gettext(), ngettext() */
+#include "ptouch.h"
+
+#define _(s) gettext(s)
+
+#define MAX_LINES 4 /* maybe this should depend on tape size */
+
+gdImage *image_load(const char *file);
+void rasterline_setpixel(uint8_t rasterline[16], int pixel);
+int get_baselineoffset(char *text, char *font, int fsz);
+int find_fontsize(int want_px, char *font, char *text);
+int needed_width(char *text, char *font, int fsz);
+int print_img(ptouch_dev ptdev, gdImage *im);
+int write_png(gdImage *im, const char *file);
+gdImage *render_text(char *font, char *line[], int lines, int tape_width);
+void usage(char *progname);
+int parse_args(int argc, char **argv);
+
+// char *font_file="/usr/share/fonts/TTF/Ubuntu-M.ttf";
+// char *font_file="Ubuntu:medium";
+char *font_file="DejaVuSans";
+char *save_png=NULL;
+int verbose=0;
+int fontsize=0;
+
+/* --------------------------------------------------------------------
+ -------------------------------------------------------------------- */
+
+void rasterline_setpixel(uint8_t rasterline[16], int pixel)
+{
+ rasterline[15-(pixel/8)] |= 1<<(pixel%8);
+ return;
+}
+
+int print_img(ptouch_dev ptdev, gdImage *im)
+{
+ int d,i,k,offset,tape_width;
+ uint8_t rasterline[16];
+
+ tape_width=ptouch_getmaxwidth(ptdev);
+ /* find out whether color 0 or color 1 is darker */
+ d=(gdImageRed(im,1)+gdImageGreen(im,1)+gdImageBlue(im,1) < gdImageRed(im,0)+gdImageGreen(im,0)+gdImageBlue(im,0))?1:0;
+ if (gdImageSY(im) > tape_width) {
+ printf(_("image is too large (%ipx x %ipx)\n"), gdImageSX(im), gdImageSY(im));
+ printf(_("maximum printing width for this tape is %ipx\n"), tape_width);
+ return -1;
+ }
+ offset=64-(gdImageSY(im)/2); /* always print centered */
+ if (ptouch_rasterstart(ptdev) != 0) {
+ printf(_("ptouch_rasterstart() failed\n"));
+ return -1;
+ }
+ for (k=0; k<gdImageSX(im); k+=1) {
+ memset(rasterline, 0, sizeof(rasterline));
+ for (i=0; i<gdImageSY(im); i+=1) {
+ if (gdImageGetPixel(im, k, gdImageSY(im)-1-i) == d) {
+ rasterline_setpixel(rasterline, offset+i);
+ }
+ }
+ if (ptouch_sendraster(ptdev, rasterline, 16) != 0) {
+ printf(_("ptouch_send() failed\n"));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ Function image_load()
+ Description detect the type of a image and try to load it
+ Last update 2005-10-16
+ Status Working, should add debug info
+ -------------------------------------------------------------------- */
+
+gdImage *image_load(const char *file)
+{
+ const uint8_t png[8]={0x89,'P','N','G',0x0d,0x0a,0x1a,0x0a};
+ char d[10];
+ FILE *f;
+ gdImage *img=NULL;
+
+ if ((f = fopen(file, "rb")) == NULL) { /* error cant open file */
+ return NULL;
+ }
+ if (fread(d, sizeof(d), 1, f) != 1) {
+ return NULL;
+ }
+ rewind(f);
+ if (memcmp(d, png, 8) == 0) {
+ img=gdImageCreateFromPng(f);
+ }
+ fclose(f);
+ return img;
+}
+
+int write_png(gdImage *im, const char *file)
+{
+ FILE *f;
+
+ if ((f = fopen(file, "wb")) == NULL) {
+ printf(_("writing image '%s' failed\n"), file);
+ return -1;
+ }
+ gdImagePng(im, f);
+ fclose(f);
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ Find out the difference in pixels between a "normal" char and one
+ that goes below the font baseline
+ -------------------------------------------------------------------- */
+int get_baselineoffset(char *text, char *font, int fsz)
+{
+ int brect[8];
+
+ if (strpbrk(text, "QgjpqyQ") == NULL) { /* if we have none of these */
+ return 0; /* we don't need an baseline offset */
+ } /* else we need to calculate it */
+ gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, "o");
+ int tmp=brect[1]-brect[5];
+ gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, "g");
+ return (brect[1]-brect[5])-tmp;
+}
+
+/* --------------------------------------------------------------------
+ Find out which fontsize we need for a given font to get a
+ specified pixel size
+ -------------------------------------------------------------------- */
+int find_fontsize(int want_px, char *font, char *text)
+{
+ int save=0;
+ int brect[8];
+
+ for (int i=4; ; i++) {
+ if (gdImageStringFT(NULL, &brect[0], -1, font, i, 0.0, 0, 0, text) != NULL) {
+ break;
+ }
+ if (brect[1]-brect[5] <= want_px) {
+ save=i;
+ } else {
+ break;
+ }
+ }
+ if (save == 0) {
+ return -1;
+ }
+ return save;
+}
+
+int needed_width(char *text, char *font, int fsz)
+{
+ int brect[8];
+
+ if (gdImageStringFT(NULL, &brect[0], -1, font, fsz, 0.0, 0, 0, text) != NULL) {
+ return -1;
+ }
+ return brect[2]-brect[0];
+}
+
+gdImage *render_text(char *font, char *line[], int lines, int tape_width)
+{
+ int brect[8];
+ int i, black, x=0, tmp, fsz=0, ofs;
+ char *p;
+ gdImage *im=NULL;
+
+// printf(_("%i lines, font = '%s'\n"), lines, font);
+ if (gdFTUseFontConfig(1) != GD_TRUE) {
+ printf(_("warning: font config not available\n"));
+ }
+ if (fontsize > 0) {
+ fsz=fontsize;
+ printf(_("setting font size=%i\n"), fsz);
+ } else {
+ for (i=0; i<lines; i++) {
+ if ((tmp=find_fontsize(tape_width/lines, font, line[i])) < 0) {
+ printf(_("could not estimate needed font size\n"));
+ return NULL;
+ }
+ if ((fsz == 0) || (tmp < fsz)) {
+ fsz=tmp;
+ }
+ }
+ printf(_("choosing font size=%i\n"), fsz);
+ }
+ for(i=0; i<lines; i++) {
+ tmp=needed_width(line[i], font_file, fsz);
+ if (tmp > x) {
+ x=tmp;
+ }
+ }
+ im=gdImageCreatePalette(x, tape_width);
+ gdImageColorAllocate(im, 255, 255, 255);
+ black=gdImageColorAllocate(im, 0, 0, 0);
+ /* gdImageStringFT(im,brect,fg,fontlist,size,angle,x,y,string) */
+ for (i=0; i<lines; i++) {
+ if ((p=gdImageStringFT(NULL, &brect[0], -black, font, fsz, 0.0, 0, 0, line[i])) != NULL) {
+ printf(_("error in gdImageStringFT: %s\n"), p);
+ }
+ tmp=brect[1]-brect[5];
+ ofs=get_baselineoffset(line[i], font_file, fsz);
+// printf("line %i height = %ipx, pos = %i\n", i+1, tmp, i*(tape_width/lines)+tmp-ofs-1);
+ if ((p=gdImageStringFT(im, &brect[0], -black, font, fsz, 0.0, 0, i*(tape_width/lines)+tmp-ofs-1, line[i])) != NULL) {
+ printf(_("error in gdImageStringFT: %s\n"), p);
+ }
+ }
+ return im;
+}
+
+void usage(char *progname)
+{
+ printf("usage: %s [options] <print-command(s)>\n", progname);
+ printf("options:\n");
+ printf("\t--font <file>\t\tuse font <file> or <name>\n");
+ printf("\t--writepng <file>\tinstead of printing, write output to png file\n");
+ printf("\t\t\t\tThis currently works only when using\n\t\t\t\tEXACTLY ONE --text statement\n");
+ printf("print-commands:\n");
+ printf("\t--image <file>\t\tprint the given image which must be a 2 color\n");
+ printf("\t\t\t\t(black/white) png\n");
+ printf("\t--text <text>\t\tPrint 1-4 lines of text.\n");
+ printf("\t\t\t\tIf the text contains spaces, use quotation marks\n\t\t\t\taround it.\n");
+ printf("\t--cutmark\t\tPrint a mark where the tape should be cut\n");
+ exit(1);
+}
+
+/* here we don't print anything, but just try to catch syntax errors */
+int parse_args(int argc, char **argv)
+{
+ int lines, i;
+
+ for (i=1; i<argc; i++) {
+ if (*argv[i] != '-') {
+ break;
+ }
+ if (strcmp(&argv[i][1], "-font") == 0) {
+ if (i+1<argc) {
+ font_file=argv[++i];
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-fontsize") == 0) {
+ if (i+1<argc) {
+ i++;
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-writepng") == 0) {
+ if (i+1<argc) {
+ save_png=argv[++i];
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-cutmark") == 0) {
+ continue; /* not done here */
+ } else if (strcmp(&argv[i][1], "-info") == 0) {
+ continue; /* not done here */
+ } else if (strcmp(&argv[i][1], "-image") == 0) {
+ if (i+1<argc) {
+ i++;
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-text") == 0) {
+ for (lines=0; (lines < MAX_LINES) && (i < argc); lines++) {
+ if ((i+1 >= argc) || (argv[i+1][0] == '-')) {
+ break;
+ }
+ i++;
+ }
+ } else if (strcmp(&argv[i][1], "-version") == 0) {
+ printf(_("ptouch-print version %s by Dominic Radermacher\n"), VERSION);
+ exit(0);
+ } else {
+ usage(argv[0]);
+ }
+ }
+ return i;
+}
+
+int main(int argc, char *argv[])
+{
+ int i, lines, tape_width;
+ char *line[MAX_LINES];
+ gdImage *im=NULL;
+ ptouch_dev ptdev=NULL;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ i=parse_args(argc, argv);
+ if (i != argc) {
+ usage(argv[0]);
+ }
+ if ((ptouch_open(&ptdev)) < 0) {
+ return 5;
+ }
+ if (ptouch_init(ptdev) != 0) {
+ printf(_("ptouch_init() failed\n"));
+ }
+ if (ptouch_getstatus(ptdev) != 0) {
+ printf(_("ptouch_getstatus() failed\n"));
+ return 1;
+ }
+ tape_width=ptouch_getmaxwidth(ptdev);
+ for (i=1; i<argc; i++) {
+ if (*argv[i] != '-') {
+ break;
+ }
+ if (strcmp(&argv[i][1], "-font") == 0) {
+ if (i+1<argc) {
+ font_file=argv[++i];
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-fontsize") == 0) {
+ if (i+1<argc) {
+ fontsize=strtol(argv[++i], NULL, 10);
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-writepng") == 0) {
+ if (i+1<argc) {
+ save_png=argv[++i];
+ } else {
+ usage(argv[0]);
+ }
+ } else if (strcmp(&argv[i][1], "-info") == 0) {
+ printf(_("maximum printing width for this tape is %ipx\n"), tape_width);
+ exit(0);
+ } else if (strcmp(&argv[i][1], "-image") == 0) {
+ im=image_load(argv[++i]);
+ if (im != NULL) {
+ print_img(ptdev, im);
+ gdImageDestroy(im);
+ }
+ } else if (strcmp(&argv[i][1], "-text") == 0) {
+ for (lines=0; (lines < MAX_LINES) && (i < argc); lines++) {
+ if ((i+1 >= argc) || (argv[i+1][0] == '-')) {
+ break;
+ }
+ i++;
+ line[lines]=argv[i];
+ }
+ if ((im=render_text(font_file, line, lines, tape_width)) == NULL) {
+ printf(_("could not render text\n"));
+ return 1;
+ }
+ if (save_png != NULL) {
+ write_png(im, save_png);
+ } else {
+ print_img(ptdev, im);
+ }
+ gdImageDestroy(im);
+ } else if (strcmp(&argv[i][1], "-cutmark") == 0) {
+ ptouch_cutmark(ptdev);
+ } else {
+ usage(argv[0]);
+ }
+ }
+ if (ptouch_eject(ptdev) != 0) {
+ printf(_("ptouch_eject() failed\n"));
+ return -1;
+ }
+ ptouch_close(ptdev);
+ libusb_exit(NULL);
+ return 0;
+}