pax_global_header00006660000000000000000000000064143711136210014511gustar00rootroot0000000000000052 comment=f4052cac47583969f4839b384d21d315e6da188d dov-paps-f4052ca/000077500000000000000000000000001437111362100136505ustar00rootroot00000000000000dov-paps-f4052ca/.gitignore000066400000000000000000000010401437111362100156330ustar00rootroot00000000000000/*.bak /*.lo /*.o /*.orig /*.rej /*.tab.c /*~ /.*.sw[nop] /.deps /.dirstamp /.gitignore /.libs /GPATH /GRTAGS /GSYMS /GTAGS /ID /Makefile /Makefile.in /TAGS /_libs /aclocal.m4 /autom4te.cache /config /config.cache /config.h /config.log /config.lt /config.status /config.status.lineno /configure /configure.lineno /intltool-extract.in /intltool-merge.in /intltool-update.in /libtool /po/*.gmo /po/*.mo /po/.intltool-merge-cache /po/Makefile /po/Makefile.in /po/Makefile.in.in /po/POTFILES /po/paps.pot /po/stamp-it /so_locations /stamp-h1 /tags dov-paps-f4052ca/AUTHORS000066400000000000000000000000461437111362100147200ustar00rootroot00000000000000Dov Grobgeld dov-paps-f4052ca/COPYING.LIB000066400000000000000000000614471437111362100153240ustar00rootroot00000000000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library 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 Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "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 LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY 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 LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! dov-paps-f4052ca/ChangeLog000066400000000000000000000155561437111362100154360ustar00rootroot000000000000002022-12-17 gettextize * m4/gettext.m4: Upgrade to gettext-0.21. * m4/host-cpu-c-abi.m4: New file, from gettext-0.21. * m4/iconv.m4: Upgrade to gettext-0.21. * m4/intlmacosx.m4: Upgrade to gettext-0.21. * m4/lib-ld.m4: Upgrade to gettext-0.21. * m4/lib-link.m4: Upgrade to gettext-0.21. * m4/lib-prefix.m4: Upgrade to gettext-0.21. * m4/nls.m4: Upgrade to gettext-0.21. * m4/po.m4: Upgrade to gettext-0.21. * m4/progtest.m4: Upgrade to gettext-0.21. 2015-08-16 Dov Grobgeld * paps.c : Ported to cairo and removed libpaps as it is not needed anymore. 2007-04-13 Dov Grobgeld * paps.c: Erased --justify option since it is not implemented in pango yet. 2007-01-19 Dov Grobgeld * configure.in: Bumped version to 0.6.8 * src/libpaps.c: Removed warnings. * src/paps.c: Added --help info about units. * src/paps.1: Added info about units. 2006-12-07 Dov Grobgeld * paps.1: Fixed bug in documentation of the --markup option. 2006-11-28 Dov Grobgeld * libpaps.h: Minor doxygen warning fixes. * doc/Doxyfile, doc/Makefile.am: Removed for new doxygen support. * aminclude.am, acinclude.m4 : Added for doxygen support * configure.in: Made doxygen documentation build at autoconf time (package preparer) and not at user configuration time. 2006-11-03 Dov Grobgeld * configure.in: Bumped version to 0.6.7 * src/paps.1: Described the new options. * src/paps.c: (split_text_into_paragraphs) Reverted to old split_text_into_paragraphs as I couldn't understand Akira's code and I don't think it is relevant anymore with the new cpi/lpi interpretation. (split_text_into_paragraphs) Added functionality for using markup. - Added option --markup for printing pango markup'd text. - Changed the interpretation of LPI so that it only controls the line spacing and not the size of the characters. - Added option --stretch-chars to stretch characters to fill the --lpi value. - Removed global variables lpi and cpi and moved them into page_layout_t . - Changed creation of options to allow passing the page_layout_t as a parameter. - Removed all references to wchar as it is not used anymore. (It shouldn't have been used in the first place as there are plenty of utf8 and ucs4 manipulating function in glib.) * src/libpaps.c: Moved the stretching of characters to c-level only. Erased the scale_x and scale_y parameters from most functions. 2006-09-07 Akira TAGOH * src/paps.c (_paps_arg_lpi_cb): new function. (_paps_arg_cpi_cb): new function. (main): added --lpi and --cpi option. (#1472021) (split_text_into_paragraphs): need to adjust the layout to avoid the cutting off after scaling with LPI/CPI parameters. (split_paragraphs_into_lines): figure out the scaling. (output_pages): likewise. (draw_line_to_page, draw_page_header_line_to_page): modified to give the scaling according to LPI/CPI to libpaps. * src/libpaps.c (paps_set_scale): new function. (paps_new, paps_layout_to_postscript_strdup) (paps_layout_line_to_postscript_strdup, add_postscript_prologue) (add_line_to_postscript, draw_contour, draw_bezier_outline): modified to output the PostScript file with any scaling. * src/paps.c: added the missing header file. (main): added --font option instead of --font-scale and --family, which works like specifying PangoFontDescription. (#1512382) (get_language): new function. (main): give a proper language to PangoContext. (#1512384) (split_text_into_paragraphs): support the wordwrap from Pango. (#1512385) * src/paps.1: removed --font-scale and --family description and added --font instead. * src/paps.c (split_text_into_paragraphs) (split_paragraphs_into_lines, output_pages): formfeed support that is originally written by Jan Willem Stumpel (main, read_file): added --encoding option support. (#1494769) 2006-05-25 Akira TAGOH * src/paps.1: fixed a typo. (#1491827) * src/paps.c (main): changed an option name --font_scale to --font-scale according to other options prefers a hyphen other than underscore. * src/paps.c (split_text_into_paragraphs): fixed a possible segfault issue. 2006-05-03 Dov Grobgeld * Release new version 0.6.6 * src/paps.c: Added #include to fix compilation errors. 2006-04-26 Dov Grobgeld * src/libpaps.c: Got rid of dead old crud. * src/libpaps.c: Defined PANGO_GLYPH_EMPTY that is not exported from pango. * src/libpaps.c: Ignore characters that FT_Load_Glyph returns an error code about. 2006-04-17 Dov Grobgeld * Release new version 0.6.5 * src/paps.1: Fixed errors in option documentations. * configure.in: Bumped version to 0.6.5 * src/paps.c: Made header separation independant on font scale. * src/paps.c: Made header font description independent on font scale. * doc/mainpage.h: Fixed typo. * src/paps.c: Output GOption parser message when parsing fails. * src/paps.1: Fixed man page so that it corresponds to goption parser. * src/paps.c: Fixed header position so that it takes margins into account. * src/Makefile.am: Added pango.1 to EXTRA_DIST to make it part of tar file. 2006-04-09 Dov Grobgeld * src/paps.c: Added tagoh's header and footer patch. * src/paps.c: Added tagoh's goption patch. 2006-04-08 Dov Grobgeld * Release new version 0.6.4 * src/paps.1: Added man page contributed by Lior Kaplan. 2006-03-28 Dov Grobgeld * src/paps.c: Applied tagoh's patch for setting the page size in PostScript. * src/paps.c: Fixed linebreaks in --help printout. 2005-12-22 Dov Grobgeld * Released new bugfix version 0.6.3 * src/libpaps.c: Fixed overflow of static hash character size. 2005-12-20 Dov Grobgeld * Released new version 0.6.2 * src/libpaps.c: Skip bitmap glyphs in order not to crash in decomposition. * src/paps.c: Created external for margin settings. * src/libpaps.c: Fixed default font to monospace per Jan Willem Stumpel suggestion. * src/paps.c: Fixed printing of row that lacks a trailing newline. 2005-11-24 Dov Grobgeld * src/libpaps.c: Fixed potential sprintf buffer overrun bug. * src/paps.c: Added options for letter and legal paper sizes * src/paps.c: Added postscript commands for setting page size * src/paps.c: Added DSC comments for orientation 2005-11-19 Dov Grobgeld * Released new version 0.6.1 * src/libpaps.c: Fixed scaling bug in output postscript. The characters were to small by a factor of 72/64 due to different coordinate systems in PostScript and freetype2. * src/libpaps.c: Various cleanup of the library. dov-paps-f4052ca/INSTALL000066400000000000000000000366261437111362100147160ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command './configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the 'README' file for instructions specific to this package. Some packages provide this 'INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The 'configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a 'Makefile' in each directory of the package. It may also create one or more '.h' files containing system-dependent definitions. Finally, it creates a shell script 'config.status' that you can run in the future to recreate the current configuration, and a file 'config.log' containing compiler output (useful mainly for debugging 'configure'). It can also use an optional file (typically called 'config.cache' and enabled with '--cache-file=config.cache' or simply '-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how 'configure' could check whether to do them, and mail diffs or instructions to the address given in the 'README' so they can be considered for the next release. If you are using the cache, and at some point 'config.cache' contains results you don't want to keep, you may remove or edit it. The file 'configure.ac' (or 'configure.in') is used to create 'configure' by a program called 'autoconf'. You need 'configure.ac' if you want to change it or regenerate 'configure' using a newer version of 'autoconf'. The simplest way to compile this package is: 1. 'cd' to the directory containing the package's source code and type './configure' to configure the package for your system. Running 'configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type 'make' to compile the package. 3. Optionally, type 'make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type 'make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the 'make install' phase executed with root privileges. 5. Optionally, type 'make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior 'make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing 'make clean'. To also remove the files that 'configure' created (so you can compile the package for a different kind of computer), type 'make distclean'. There is also a 'make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type 'make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide 'make distcheck', which can by used by developers to test that all other targets like 'make install' and 'make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the 'configure' script does not know about. Run './configure --help' for details on some of the pertinent environment variables. You can give 'configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU 'make'. 'cd' to the directory where you want the object files and executables to go and run the 'configure' script. 'configure' automatically checks for the source code in the directory that 'configure' is in and in '..'. This is known as a "VPATH" build. With a non-GNU 'make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use 'make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple '-arch' options to the compiler but only a single '-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the 'lipo' tool if you have problems. Installation Names ================== By default, 'make install' installs the package's commands under '/usr/local/bin', include files under '/usr/local/include', etc. You can specify an installation prefix other than '/usr/local' by giving 'configure' the option '--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option '--exec-prefix=PREFIX' to 'configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like '--bindir=DIR' to specify different values for particular kinds of files. Run 'configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of '${prefix}', so that specifying just '--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to 'configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the 'make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, 'make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of '${prefix}'. Any directories that were specified during 'configure', but not in terms of '${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the 'DESTDIR' variable. For example, 'make install DESTDIR=/alternate/directory' will prepend '/alternate/directory' before all installation names. The approach of 'DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of '${prefix}' at 'configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving 'configure' the option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'. Some packages pay attention to '--enable-FEATURE' options to 'configure', where FEATURE indicates an optional part of the package. They may also pay attention to '--with-PACKAGE' options, where PACKAGE is something like 'gnu-as' or 'x' (for the X Window System). The 'README' should mention any '--enable-' and '--with-' options that the package recognizes. For packages that use the X Window System, 'configure' can usually find the X include and library files automatically, but if it doesn't, you can use the 'configure' options '--x-includes=DIR' and '--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of 'make' will be. For these packages, running './configure --enable-silent-rules' sets the default to minimal output, which can be overridden with 'make V=1'; while running './configure --disable-silent-rules' sets the default to verbose, which can be overridden with 'make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX 'make' updates targets which have the same timestamps as their prerequisites, which makes it generally unusable when shipped generated files such as 'configure' are involved. Use GNU 'make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its '' header file. The option '-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put '/usr/ucb' early in your 'PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in '/usr/bin'. So, if you need '/usr/ucb' in your 'PATH', put it _after_ '/usr/bin'. On Haiku, software installed for all users goes in '/boot/common', not '/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features 'configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, 'configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the '--build=TYPE' option. TYPE can either be a short name for the system type, such as 'sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file 'config.sub' for the possible values of each field. If 'config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option '--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with '--host=TYPE'. Sharing Defaults ================ If you want to set default values for 'configure' scripts to share, you can create a site shell script called 'config.site' that gives default values for variables like 'CC', 'cache_file', and 'prefix'. 'configure' looks for 'PREFIX/share/config.site' if it exists, then 'PREFIX/etc/config.site' if it exists. Or, you can set the 'CONFIG_SITE' environment variable to the location of the site script. A warning: not all 'configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to 'configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the 'configure' command line, using 'VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified 'gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash 'configure' Invocation ====================== 'configure' recognizes the following options to control how it operates. '--help' '-h' Print a summary of all of the options to 'configure', and exit. '--help=short' '--help=recursive' Print a summary of the options unique to this package's 'configure', and exit. The 'short' variant lists options used only in the top level, while the 'recursive' variant lists options also present in any nested packages. '--version' '-V' Print the version of Autoconf used to generate the 'configure' script, and exit. '--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally 'config.cache'. FILE defaults to '/dev/null' to disable caching. '--config-cache' '-C' Alias for '--cache-file=config.cache'. '--quiet' '--silent' '-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to '/dev/null' (any error messages will still be shown). '--srcdir=DIR' Look for the package's source code in directory DIR. Usually 'configure' can determine that directory automatically. '--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. '--no-create' '-n' Run the configure checks, but stop before creating any output files. 'configure' also accepts some other, not widely useful, options. Run 'configure --help' for more details. dov-paps-f4052ca/INSTALL.md000066400000000000000000000003761437111362100153060ustar00rootroot00000000000000## Installation instructions paps is preferably compiled with meson, though automake is supported as well ## Dependencies - Meson 0.55.0 or later - https://github.com/fmtlib/fmt - fmtlib - C++17 ## Compilation ``` meson build cd build && ninja ``` dov-paps-f4052ca/Makefile.am000066400000000000000000000022221437111362100157020ustar00rootroot00000000000000NULL = ACLOCAL_AMFLAGS=-I m4 SUBDIRS = src po EXTRA_DIST = autogen.sh intltool-extract.in intltool-merge.in intltool-update.in MAINTAINERCLEANFILES = \ $(srcdir)/aclocal.m4 \ $(builddir)/config \ $(NULL) -include $(top_srcdir)/git.mk check-gettext: @if test x$(USE_NLS) != "xyes" ; then echo "Missing gettext. Rerun configure and check for" \ "'checking whether to use NLS... yes'!" ; exit 1 ; fi update-po: check-gettext @find $(srcdir)/src/ -name "*.cc" -print | sort > $(srcdir)/po/POTFILES.in.2 ; \ if diff $(srcdir)/po/POTFILES.in $(srcdir)/po/POTFILES.in.2 >/dev/null 2>&1 ; then \ rm -f $(srcdir)/po/POTFILES.in.2 ; \ else \ mv $(srcdir)/po/POTFILES.in.2 $(srcdir)/po/POTFILES.in ; \ fi cd po && $(MAKE) $(AM_MAKEFLAGS) update-po force-update-gmo: check-gettext touch po/*.po cd po && $(MAKE) $(AM_MAKEFLAGS) update-gmo force-update-gmo-%: check-gettext @language=`echo $@ | sed s/force-update-gmo-//` ; \ if test ! -f po/$$language.po ; then echo "file po/$$language.po does not exist" ; exit 1 ; fi ; \ touch po/$$language.po ; \ cd po && $(MAKE) $(AM_MAKEFLAGS) update-gmo .PHONY: check-gettext update-po update-gmo force-update-gmo dov-paps-f4052ca/NEWS000066400000000000000000000020061437111362100143450ustar00rootroot00000000000000Overview of changes between 0.7.9 and 0.8.0 ============================================= * Fixed minor bugs from 0.7.9 * Fixed bug when using markup with char mapping and visible wrap marker. * Added src-to-paps preprocessor scripts for conversion of source code to paps through GNU Highlight. Overview of changes between 0.7.0 and 0.7.9 ============================================= * Switch to C++17 * The header and footers are now modifiable by a syntax borrowed from python and the fmt library. E.g. the following command line shows what is possible: paps --header-left="{now:%Y-%m-%d %H:%M}" --header-center="{path}" --header-right="Page {page_idx:02d}/{num_pages:02d}" --header -o hello.pdf paps.cc * Add separation line option Overview of changes between 0.7.0 and 0.7.1 ============================================= * Added initial meson compilation support. * Minor accumulated bug fixes since 0.7.0 Older news ============================================= * 2015-08-16 Sun Ported paps to cairo dov-paps-f4052ca/README000066400000000000000000000000171437111362100145260ustar00rootroot00000000000000See: README.md dov-paps-f4052ca/README.md000066400000000000000000000034211437111362100151270ustar00rootroot00000000000000# About paps is a command line program for converting Unicode text encoded in UTF-8 to postscript and pdf by using pango. # Installation instructions See file:INSTALL.md # Example Here is the output from processing the file misc/small-hello.utf8: ![Example image](misc/small-hello.png) # History paps was written around 2005 to enable printing of plain text unicode UTF-8 files. It is named by the use of the excellent Pango library (from which it took its first two characters) and outputed postscript (ps, the last two characters). When the initial version was written, there was no simple way of translating the output of pango to postscript outlines, and therefore initially output bitmap fonts in the postscript output. But I wanted to have resolution independent postscript, and therefore in a subsequent version Ι wrote my own font encoding library in PostScript, by making use of the fact that PostScript is a full programming language. This worked well when sending the result to a PostScript printer, but the use of this library had some serious disadvantages: - When converting to pdf you got huge files (two orders of magnitude larger!) since in contrast to PostScript, PDF is not a programming language, and therefore each glyph would be encoded as a PDF path. - You couldn't select and copy and paste from the resulting postscript file, since there was no underlying text, only graphic paths. In the early 2010's the library cairo and its accompanying pangocairo library finally created an easy way of converting pango output to postscript in an idiomatic way. But it took me several years until I finally rewrote paps to make use of them. But I finally did so and released the resulting version on github in 2015 as version 0.7.0 . # Usage Run `paps --help` for getting help. dov-paps-f4052ca/acinclude.m4000066400000000000000000000264121437111362100160460ustar00rootroot00000000000000# This file is part of Autoconf. -*- Autoconf -*- # Copyright (C) 2004 Oren Ben-Kiki # This file is distributed under the same terms as the Autoconf macro files. # Generate automatic documentation using Doxygen. Works in concert with the # aminclude.m4 file and a compatible doxygen configuration file. Defines the # following public macros: # # DX_???_FEATURE(ON|OFF) - control the default setting fo a Doxygen feature. # Supported features are 'DOXYGEN' itself, 'DOT' for generating graphics, # 'HTML' for plain HTML, 'CHM' for compressed HTML help (for MS users), 'CHI' # for generating a seperate .chi file by the .chm file, and 'MAN', 'RTF', # 'XML', 'PDF' and 'PS' for the appropriate output formats. The environment # variable DOXYGEN_PAPER_SIZE may be specified to override the default 'a4wide' # paper size. # # By default, HTML, PDF and PS documentation is generated as this seems to be # the most popular and portable combination. MAN pages created by Doxygen are # usually problematic, though by picking an appropriate subset and doing some # massaging they might be better than nothing. CHM and RTF are specific for MS # (note that you can't generate both HTML and CHM at the same time). The XML is # rather useless unless you apply specialized post-processing to it. # # The macro mainly controls the default state of the feature. The use can # override the default by specifying --enable or --disable. The macros ensure # that contradictory flags are not given (e.g., --enable-doxygen-html and # --enable-doxygen-chm, --enable-doxygen-anything with --disable-doxygen, etc.) # Finally, each feature will be automatically disabled (with a warning) if the # required programs are missing. # # Once all the feature defaults have been specified, call DX_INIT_DOXYGEN with # the following parameters: a one-word name for the project for use as a # filename base etc., an optional configuration file name (the default is # 'Doxyfile', the same as Doxygen's default), and an optional output directory # name (the default is 'doxygen-doc'). ## ----------## ## Defaults. ## ## ----------## DX_ENV="" AC_DEFUN([DX_FEATURE_doc], ON) AC_DEFUN([DX_FEATURE_dot], ON) AC_DEFUN([DX_FEATURE_man], OFF) AC_DEFUN([DX_FEATURE_html], ON) AC_DEFUN([DX_FEATURE_chm], OFF) AC_DEFUN([DX_FEATURE_chi], OFF) AC_DEFUN([DX_FEATURE_rtf], OFF) AC_DEFUN([DX_FEATURE_xml], OFF) AC_DEFUN([DX_FEATURE_pdf], ON) AC_DEFUN([DX_FEATURE_ps], ON) ## --------------- ## ## Private macros. ## ## --------------- ## # DX_ENV_APPEND(VARIABLE, VALUE) # ------------------------------ # Append VARIABLE="VALUE" to DX_ENV for invoking doxygen. AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])]) # DX_DIRNAME_EXPR # --------------- # Expand into a shell expression prints the directory part of a path. AC_DEFUN([DX_DIRNAME_EXPR], [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']]) # DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF) # ------------------------------------- # Expands according to the M4 (static) status of the feature. AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])]) # DX_REQUIRE_PROG(VARIABLE, PROGRAM) # ---------------------------------- # Require the specified program to be found for the DX_CURRENT_FEATURE to work. AC_DEFUN([DX_REQUIRE_PROG], [ AC_PATH_TOOL([$1], [$2]) if test "$DX_FLAG_DX_CURRENT_FEATURE$$1" = 1; then AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION]) AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0) fi ]) # DX_TEST_FEATURE(FEATURE) # ------------------------ # Expand to a shell expression testing whether the feature is active. AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1]) # DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE) # ------------------------------------------------- # Verify that a required features has the right state before trying to turn on # the DX_CURRENT_FEATURE. AC_DEFUN([DX_CHECK_DEPEND], [ test "$DX_FLAG_$1" = "$2" \ || AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1, requires, contradicts) doxygen-DX_CURRENT_FEATURE]) ]) # DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE) # ---------------------------------------------------------- # Turn off the DX_CURRENT_FEATURE if the required feature is off. AC_DEFUN([DX_CLEAR_DEPEND], [ test "$DX_FLAG_$1" = "$2" || AC_SUBST([DX_FLAG_DX_CURRENT_FEATURE], 0) ]) # DX_FEATURE_ARG(FEATURE, DESCRIPTION, # CHECK_DEPEND, CLEAR_DEPEND, # REQUIRE, DO-IF-ON, DO-IF-OFF) # -------------------------------------------- # Parse the command-line option controlling a feature. CHECK_DEPEND is called # if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND), # otherwise CLEAR_DEPEND is called to turn off the default state if a required # feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional # requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and # DO-IF-ON or DO-IF-OFF are called according to the final state of the feature. AC_DEFUN([DX_ARG_ABLE], [ AC_DEFUN([DX_CURRENT_FEATURE], [$1]) AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2]) AC_ARG_ENABLE(doxygen-$1, [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1], [--enable-doxygen-$1]), DX_IF_FEATURE([$1], [don't $2], [$2]))], [ case "$enableval" in #( y|Y|yes|Yes|YES) AC_SUBST([DX_FLAG_$1], 1) $3 ;; #( n|N|no|No|NO) AC_SUBST([DX_FLAG_$1], 0) ;; #( *) AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1]) ;; esac ], [ AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)]) $4 ]) if DX_TEST_FEATURE([$1]); then $5 : fi if DX_TEST_FEATURE([$1]); then AM_CONDITIONAL(DX_COND_$1, :) $6 : else AM_CONDITIONAL(DX_COND_$1, false) $7 : fi ]) ## -------------- ## ## Public macros. ## ## -------------- ## # DX_XXX_FEATURE(DEFAULT_STATE) # ----------------------------- AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc], [$1])]) AC_DEFUN([DX_MAN_FEATURE], [AC_DEFUN([DX_FEATURE_man], [$1])]) AC_DEFUN([DX_HTML_FEATURE], [AC_DEFUN([DX_FEATURE_html], [$1])]) AC_DEFUN([DX_CHM_FEATURE], [AC_DEFUN([DX_FEATURE_chm], [$1])]) AC_DEFUN([DX_CHI_FEATURE], [AC_DEFUN([DX_FEATURE_chi], [$1])]) AC_DEFUN([DX_RTF_FEATURE], [AC_DEFUN([DX_FEATURE_rtf], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_XML_FEATURE], [AC_DEFUN([DX_FEATURE_xml], [$1])]) AC_DEFUN([DX_PDF_FEATURE], [AC_DEFUN([DX_FEATURE_pdf], [$1])]) AC_DEFUN([DX_PS_FEATURE], [AC_DEFUN([DX_FEATURE_ps], [$1])]) # DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR]) # --------------------------------------------------------- # PROJECT also serves as the base name for the documentation files. # The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc". AC_DEFUN([DX_INIT_DOXYGEN], [ # Files: AC_SUBST([DX_PROJECT], [$1]) AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])]) AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])]) # Environment variables used inside doxygen.cfg: DX_ENV_APPEND(SRCDIR, $srcdir) DX_ENV_APPEND(PROJECT, $DX_PROJECT) DX_ENV_APPEND(DOCDIR, $DX_DOCDIR) DX_ENV_APPEND(VERSION, $PACKAGE_VERSION) # Doxygen itself: DX_ARG_ABLE(doc, [generate any doxygen documentation], [], [], [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen) DX_REQUIRE_PROG([DX_PERL], perl)], [DX_ENV_APPEND(PERL_PATH, $DX_PERL)]) # Dot for graphics: DX_ARG_ABLE(dot, [generate graphics for doxygen documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_DOT], dot)], [DX_ENV_APPEND(HAVE_DOT, YES) DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])], [DX_ENV_APPEND(HAVE_DOT, NO)]) # Man pages generation: DX_ARG_ABLE(man, [generate doxygen manual pages], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_MAN, YES)], [DX_ENV_APPEND(GENERATE_MAN, NO)]) # RTF file generation: DX_ARG_ABLE(rtf, [generate doxygen RTF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_RTF, YES)], [DX_ENV_APPEND(GENERATE_RTF, NO)]) # XML file generation: DX_ARG_ABLE(xml, [generate doxygen XML documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [], [DX_ENV_APPEND(GENERATE_XML, YES)], [DX_ENV_APPEND(GENERATE_XML, NO)]) # (Compressed) HTML help generation: DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_HHC], hhc)], [DX_ENV_APPEND(HHC_PATH, $DX_HHC) DX_ENV_APPEND(GENERATE_HTML, YES) DX_ENV_APPEND(GENERATE_HTMLHELP, YES)], [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)]) # Seperate CHI file generation. DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file], [DX_CHECK_DEPEND(chm, 1)], [DX_CLEAR_DEPEND(chm, 1)], [], [DX_ENV_APPEND(GENERATE_CHI, YES)], [DX_ENV_APPEND(GENERATE_CHI, NO)]) # Plain HTML pages generation: DX_ARG_ABLE(html, [generate doxygen plain HTML documentation], [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)], [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)], [], [DX_ENV_APPEND(GENERATE_HTML, YES)], [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)]) # PostScript file generation: DX_ARG_ABLE(ps, [generate doxygen PostScript documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_LATEX], latex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_DVIPS], dvips) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # PDF file generation: DX_ARG_ABLE(pdf, [generate doxygen PDF documentation], [DX_CHECK_DEPEND(doc, 1)], [DX_CLEAR_DEPEND(doc, 1)], [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex) DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex) DX_REQUIRE_PROG([DX_EGREP], egrep)]) # LaTeX generation for PS and/or PDF: if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then AM_CONDITIONAL(DX_COND_latex, :) DX_ENV_APPEND(GENERATE_LATEX, YES) else AM_CONDITIONAL(DX_COND_latex, false) DX_ENV_APPEND(GENERATE_LATEX, NO) fi # Paper size for PS and/or PDF: AC_ARG_VAR(DOXYGEN_PAPER_SIZE, [a4wide (default), a4, letter, legal or executive]) case "$DOXYGEN_PAPER_SIZE" in #( "") AC_SUBST(DOXYGEN_PAPER_SIZE, "") ;; #( a4wide|a4|letter|legal|executive) DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE) ;; #( *) AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE']) ;; esac #For debugging: #echo DX_FLAG_doc=$DX_FLAG_doc #echo DX_FLAG_dot=$DX_FLAG_dot #echo DX_FLAG_man=$DX_FLAG_man #echo DX_FLAG_html=$DX_FLAG_html #echo DX_FLAG_chm=$DX_FLAG_chm #echo DX_FLAG_chi=$DX_FLAG_chi #echo DX_FLAG_rtf=$DX_FLAG_rtf #echo DX_FLAG_xml=$DX_FLAG_xml #echo DX_FLAG_pdf=$DX_FLAG_pdf #echo DX_FLAG_ps=$DX_FLAG_ps #echo DX_ENV=$DX_ENV ]) dov-paps-f4052ca/autogen.sh000077500000000000000000000002551437111362100156530ustar00rootroot00000000000000#!/bin/sh mkdir -p config m4 echo "no" | glib-gettextize --force --copy intltoolize --copy --force --automake autoreconf --force --install -I config -I m4 ./configure $* dov-paps-f4052ca/configure.ac000066400000000000000000000014641437111362100161430ustar00rootroot00000000000000dnl Process this file with autoconf to produce a configuration script AC_INIT(paps, 0.8.0, dov.grobgeld@gmail.com) AC_CONFIG_AUX_DIR(config) AC_CONFIG_SRCDIR(src/paps.cc) AC_CONFIG_HEADERS([config.h]) AM_INIT_AUTOMAKE AC_PROG_CXX AC_PROG_CC AX_COMPILER_FLAGS WARN_CFLAGS="$WARN_CFLAGS -Wno-format-y2k" dnl Requires to declare wcwidth() AC_GNU_SOURCE PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([PANGO], [pangocairo pangoft2]) PKG_CHECK_MODULES(FMT, fmt >= 6.0) AC_SUBST(FMT_CFLAGS) AC_SUBST(FMT_LIBS) AC_PROG_INTLTOOL([0.23]) GETTEXT_PACKAGE=paps AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [Package name for gettext.]) ALL_LINGUAS="" AM_GLIB_GNU_GETTEXT datadir='${prefix}/${DATADIRNAME}' AC_SUBST(datadir) AC_CONFIG_FILES([Makefile src/Makefile po/Makefile.in]) AC_OUTPUT() dov-paps-f4052ca/examples/000077500000000000000000000000001437111362100154665ustar00rootroot00000000000000dov-paps-f4052ca/examples/small-hello.utf8000066400000000000000000000005461437111362100205140ustar00rootroot00000000000000paps by Dov Grobgeld (דב גרובגלד) Printing through Παν語 (Pango) Arabic السلام عليكم Bengali (বাঙ্লা) ষাগতোম Greek (Ελληνικά) Γειά σας Hebrew שָׁלוֹם Japanese (日本語) こんにちは, コンニチハ Chinese (中文,普通话,汉语) 你好 Vietnamese (Tiếng Việt) Xin Chào dov-paps-f4052ca/git.mk000066400000000000000000000155701437111362100147740ustar00rootroot00000000000000# git.mk # # Copyright 2009, Red Hat, Inc. # Copyright 2010,2011 Behdad Esfahbod # Written by Behdad Esfahbod # # Copying and distribution of this file, with or without modification, # is permitted in any medium without royalty provided the copyright # notice and this notice are preserved. # # The latest version of this file can be downloaded from: # https://raw.github.com/behdad/git.mk/master/git.mk # Bugs, etc, should be reported upstream at: # https://github.com/behdad/git.mk # # To use in your project, import this file in your git repo's toplevel, # then do "make -f git.mk". This modifies all Makefile.am files in # your project to -include git.mk. Remember to add that line to new # Makefile.am files you create in your project, or just rerun the # "make -f git.mk". # # This enables automatic .gitignore generation. If you need to ignore # more files, add them to the GITIGNOREFILES variable in your Makefile.am. # But think twice before doing that. If a file has to be in .gitignore, # chances are very high that it's a generated file and should be in one # of MOSTLYCLEANFILES, CLEANFILES, DISTCLEANFILES, or MAINTAINERCLEANFILES. # # The only case that you need to manually add a file to GITIGNOREFILES is # when remove files in one of mostlyclean-local, clean-local, distclean-local, # or maintainer-clean-local make targets. # # Note that for files like editor backup, etc, there are better places to # ignore them. See "man gitignore". # # If "make maintainer-clean" removes the files but they are not recognized # by this script (that is, if "git status" shows untracked files still), send # me the output of "git status" as well as your Makefile.am and Makefile for # the directories involved and I'll diagnose. # # For a list of toplevel files that should be in MAINTAINERCLEANFILES, see # Makefile.am.sample in the git.mk git repo. # # Don't EXTRA_DIST this file. It is supposed to only live in git clones, # not tarballs. It serves no useful purpose in tarballs and clutters the # build dir. # # This file knows how to handle autoconf, automake, libtool, gtk-doc, # gnome-doc-utils, yelp.m4, mallard, intltool, gsettings, dejagnu. # # This makefile provides the following targets: # # - all: "make all" will build all gitignore files. # - gitignore: makes all gitignore files in the current dir and subdirs. # - .gitignore: make gitignore file for the current dir. # - gitignore-recurse: makes all gitignore files in the subdirs. # # KNOWN ISSUES: # # - Recursive configure doesn't work as $(top_srcdir)/git.mk inside the # submodule doesn't find us. If you have configure.{in,ac} files in # subdirs, add a proxy git.mk file in those dirs that simply does: # "include $(top_srcdir)/../git.mk". Add more ..'s to your taste. # And add those files to git. See vte/gnome-pty-helper/git.mk for # example. # git-all: git-mk-install git-mk-install: @echo Installing git makefile @any_failed=; \ find "`test -z "$(top_srcdir)" && echo . || echo "$(top_srcdir)"`" -name Makefile.am | while read x; do \ if grep 'include .*/git.mk' $$x >/dev/null; then \ echo $$x already includes git.mk; \ else \ failed=; \ echo "Updating $$x"; \ { cat $$x; \ echo ''; \ echo '-include $$(top_srcdir)/git.mk'; \ } > $$x.tmp || failed=1; \ if test x$$failed = x; then \ mv $$x.tmp $$x || failed=1; \ fi; \ if test x$$failed = x; then : else \ echo Failed updating $$x; >&2 \ any_failed=1; \ fi; \ fi; done; test -z "$$any_failed" .PHONY: git-all git-mk-install ### .gitignore generation $(srcdir)/.gitignore: Makefile.am $(top_srcdir)/git.mk $(AM_V_GEN) \ { \ if test "x$(DOC_MODULE)" = x -o "x$(DOC_MAIN_SGML_FILE)" = x; then :; else \ for x in \ $(DOC_MODULE)-decl-list.txt \ $(DOC_MODULE)-decl.txt \ tmpl/$(DOC_MODULE)-unused.sgml \ "tmpl/*.bak" \ xml html \ ; do echo /$$x; done; \ fi; \ if test "x$(DOC_MODULE)$(DOC_ID)" = x -o "x$(DOC_LINGUAS)" = x; then :; else \ for lc in $(DOC_LINGUAS); do \ for x in \ $(if $(DOC_MODULE),$(DOC_MODULE).xml) \ $(DOC_PAGES) \ $(DOC_INCLUDES) \ ; do echo /$$lc/$$x; done; \ done; \ for x in \ $(_DOC_OMF_ALL) \ $(_DOC_DSK_ALL) \ $(_DOC_HTML_ALL) \ $(_DOC_MOFILES) \ $(DOC_H_FILE) \ "*/.xml2po.mo" \ "*/*.omf.out" \ ; do echo /$$x; done; \ fi; \ if test "x$(HELP_ID)" = x -o "x$(HELP_LINGUAS)" = x; then :; else \ for lc in $(HELP_LINGUAS); do \ for x in \ $(HELP_FILES) \ "$$lc.stamp" \ "$$lc.mo" \ ; do echo /$$lc/$$x; done; \ done; \ fi; \ if test "x$(gsettings_SCHEMAS)" = x; then :; else \ for x in \ $(gsettings_SCHEMAS:.xml=.valid) \ $(gsettings__enum_file) \ ; do echo /$$x; done; \ fi; \ if test -f $(srcdir)/po/Makefile.in.in; then \ for x in \ po/Makefile.in.in \ po/Makefile.in \ po/Makefile \ po/POTFILES \ po/stamp-it \ po/.intltool-merge-cache \ "po/*.gmo" \ "po/*.mo" \ po/$(GETTEXT_PACKAGE).pot \ intltool-extract.in \ intltool-merge.in \ intltool-update.in \ ; do echo /$$x; done; \ fi; \ if test -f $(srcdir)/configure; then \ for x in \ autom4te.cache \ configure \ config.h \ stamp-h1 \ libtool \ config.lt \ ; do echo /$$x; done; \ fi; \ if test "x$(DEJATOOL)" = x; then :; else \ for x in \ $(DEJATOOL) \ ; do echo /$$x.sum; echo /$$x.log; done; \ echo /site.exp; \ fi; \ for x in \ .gitignore \ $(GITIGNOREFILES) \ $(CLEANFILES) \ $(PROGRAMS) $(check_PROGRAMS) $(EXTRA_PROGRAMS) \ $(LIBRARIES) $(check_LIBRARIES) $(EXTRA_LIBRARIES) \ $(LTLIBRARIES) $(check_LTLIBRARIES) $(EXTRA_LTLIBRARIES) \ so_locations \ .libs _libs \ $(MOSTLYCLEANFILES) \ "*.$(OBJEXT)" \ "*.lo" \ $(DISTCLEANFILES) \ $(am__CONFIG_DISTCLEAN_FILES) \ $(CONFIG_CLEAN_FILES) \ TAGS ID GTAGS GRTAGS GSYMS GPATH tags \ "*.tab.c" \ $(MAINTAINERCLEANFILES) \ $(BUILT_SOURCES) \ $(DEPDIR) \ Makefile \ Makefile.in \ "*.orig" \ "*.rej" \ "*.bak" \ "*~" \ ".*.sw[nop]" \ ".dirstamp" \ ; do echo /$$x; done; \ } | \ sed "s@^/`echo "$(srcdir)" | sed 's/\(.\)/[\1]/g'`/@/@" | \ sed 's@/[.]/@/@g' | \ LC_ALL=C sort | uniq > $@.tmp && \ mv $@.tmp $@; all: $(srcdir)/.gitignore gitignore-recurse-maybe gitignore: $(srcdir)/.gitignore gitignore-recurse gitignore-recurse-maybe: @for subdir in $(DIST_SUBDIRS); do \ case " $(SUBDIRS) " in \ *" $$subdir "*) :;; \ *) test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse-maybe || echo "Skipping $$subdir");; \ esac; \ done gitignore-recurse: @for subdir in $(DIST_SUBDIRS); do \ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) .gitignore gitignore-recurse || echo "Skipping $$subdir"); \ done maintainer-clean: gitignore-clean gitignore-clean: -rm -f $(srcdir)/.gitignore .PHONY: gitignore-clean gitignore gitignore-recurse gitignore-recurse-maybe dov-paps-f4052ca/m4/000077500000000000000000000000001437111362100141705ustar00rootroot00000000000000dov-paps-f4052ca/m4/pkg.m4000066400000000000000000000171671437111362100152270ustar00rootroot00000000000000# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 1 (pkg-config-0.24) # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You 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. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) # only at the first occurence in configure.ac, so if the first place # it's called might be skipped (such as if it is within an "if", you # have to call PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])# PKG_CHECK_MODULES # PKG_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable pkgconfigdir as the location where a module # should install pkg-config .pc files. By default the directory is # $libdir/pkgconfig, but the default can be changed by passing # DIRECTORY. The user can override through the --with-pkgconfigdir # parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_INSTALLDIR # PKG_NOARCH_INSTALLDIR(DIRECTORY) # ------------------------- # Substitutes the variable noarch_pkgconfigdir as the location where a # module should install arch-independent pkg-config .pc files. By # default the directory is $datadir/pkgconfig, but the default can be # changed by passing DIRECTORY. The user can override through the # --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ]) dnl PKG_NOARCH_INSTALLDIR # PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, # [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # ------------------------------------------- # Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])# PKG_CHECK_VAR dov-paps-f4052ca/meson.build000066400000000000000000000042461437111362100160200ustar00rootroot00000000000000project('paps', 'c', 'cpp', version: '0.8.0', default_options : ['cpp_std=c++17'], meson_version : '>= 0.44') fmt_dep = dependency('fmt') pkg = import('pkgconfig') pango_dep = dependency('pangoft2') cairo_dep = dependency('pangocairo') glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') # C compiler. This is the cross compiler if we're cross-compiling cc = meson.get_compiler('c') cdata = configuration_data() # Checks for library functions foreach f : ['memmove', 'memset', 'strdup'] cdata.set('HAVE_' + f.to_upper(), cc.has_function(f)) endforeach # Checks for header files # Some HAVE_FOO defines need to be defined to either 1 or 0, others need to # be defined or undefined. The code base is a bit inconsistent there. foreach h : ['stdlib.h', 'string.h', 'memory.h'] cdata.set10('HAVE_' + h.underscorify().to_upper(), cc.has_header(h)) endforeach foreach h : ['strings.h', 'sys/times.h'] cdata.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h)) endforeach # Not entirely correct, but sufficient for us. Should move away from this # ancient define and just include individual headers based on individual defs if cc.has_header('strings.h') # define to 1 or leave undefined otherwise, don't simplify cdata.set('STDC_HEADERS', 1) endif # This is available pretty much everywhere cdata.set('HAVE_STRINGIZE', 1) # Assume we have nls, since paps doesn't compile without it cdata.set('ENABLE_NLS',1) # Not really sure what this is used for, but paps doesn't compile without it. cdata.set_quoted('DATADIR','.') buildtype = get_option('buildtype') if buildtype == 'debug' or buildtype == 'debugoptimized' cdata.set('DEBUG', 1) endif cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name()) cdata.set_quoted('PACKAGE_STRING', 'paps-' + meson.project_version()) # write config.h config_h = configure_file(output: 'config.h', configuration: cdata) incs = include_directories('.', 'src') # Install the src-to-paps script with its pango_markup.outlang # dependancy. install_data(['misc/pango_markup.outlang'], install_dir : 'share/paps') install_data(['scripts/src-to-paps'], install_dir : 'bin') subdir('src') dov-paps-f4052ca/misc/000077500000000000000000000000001437111362100146035ustar00rootroot00000000000000dov-paps-f4052ca/misc/pango_markup.outlang000066400000000000000000000010551437111362100206620ustar00rootroot00000000000000extension "pango" bold "$text" italics "$text" underline "$text" color "$text" colormap "green" "#33CC00" "red" "#FF0000" "darkred" "#990000" "blue" "#0000FF" "brown" "#9A1900" "pink" "#CC33CC" "yellow" "#FFCC00" "cyan" "#66FFFF" "purple" "#993399" "orange" "#FF6600" "brightorange" "#FF9900" "brightgreen" "#33FF33" "darkgreen" "#009900" "black" "#000000" "teal" "#008080" "gray" "#808080" "darkblue" "#000080" "white" "#FFFFFF" default "#000000" end translations "&" "&" "<" "<" ">" ">" end dov-paps-f4052ca/misc/small-hello.png000066400000000000000000000506461437111362100175350ustar00rootroot00000000000000PNG  IHDRSbKGD̿ pHYs  tIME 3 IDATxKrJvө]VTTA#68 7"[n @@z=B#qϡ:'od_z쇴~["H<+Wfu5 'y{eEJVR.]]; C>qQna`ho AqQnai0rl O\T\ ~o. ~?+ .IiOO?JX V.'~|r, 0ApɈ'>G~Rq擖!RA,3rG> w~6%)O?3،nP Ahk[O" l_?3H)!B?3ƟwhFL >3)]/-A ;?G~?ߍd`x/>񳑋zcaHD ߁?G+XbaPC\ދDߌe)a+XZ=0ApZBW&^`࠭eQ/D0Ah ]*  ANFC AD0AxSt' ba ! " ` ! ! " ` !Hmޓ`(wv ԛܑ%2^x/1%3Z~&؎*&MKL%(B:ܳl7;>mFgE>#oڛE!=fx}w;|q"ϗ] v=ck/jUŜ'.fdV||`B΍ ѦsS~ՉGoqSٮWߦ sԭ{> &+ʷ+Tz<HH=B2I̘7d$ti XEq&a.~.I΀KiѧK(Q1] h3=Z{^6CtQ]"܃k'uK& db`֎Θ-,i3dŹ$KbiѥOcD(FhfDJVcw0dF'ϲHZ5!Z:U6pߚ`W+t;0YAks)3% "{iL+rҚ -r:g 2V}m|x+`n*_Y G5I15MQLQ)" 7Fn#>#%9iŷ0+/+~Zk}Sk'Z/4:04Zk֝#('4za5ܶJyƕ7Z)S놣V>IthO}X֕suݦW姁)C{+ F'v^¹40wJ!v=a1WζɁejA#t&|K?EDs?5w{aZA)W=ƽV}ЃvpsL;;U4=S⾱\{imMG&m#5;ls=fL0#l]I^=EsP9϶ 9۱$ÆgȽNYH{|͆ۄq ߺ#ãSvܗ83 rS*xd@rMڭ&@Tse{so_9?}g*67.֪\0j^)+nf+ŗ(F>}`򌹊)46xoQ G p18bIwQ8. "!vΫ θHg[x1wGLt-Ưq⍁)50{%ƣ{@f+tW4x`Qᖲi$|˖;bmeipL˭:>t u#;PNϻWyjO+F:GΐUkic{&=Z?K#7s;P08iHϩ Bs6c=sbV;<b#юĦ,b`lށK.j6!CK bֲNJIy(-yׂ10S2!"ɘ]|ۦKoxS cD贂eUa2#^sF;ގ;|SEҦ=[HGBd S\%O!93t4(`FTŅY*5"qi"0+{[< "fQU%NpC`9{1<}-[@_*6`jG YaLNAkxIpg]m< ;-{EbܩEvmy7Ӣ|lfĔ!>!y8B5Hm `h*=9烝fBĎXMH{}2c0)c<y}tz C p2" ` ! " `vct.'?#ԾÚym{& `Nb,1V B0ZGkKNd:mU(2,x:yyKGcUU;|| g~Qdtj!s?׺_cY9e$iZ@8'2^G0k*߆{S0&9rRR$@G&)1"cB !s"Y̵$b6!tr"Ԟ09ѥUvaZZ˅&'[ Vpyb&z;dN隌HYW|RIx Q$} k%:GWbvEWw:x/8Vh~H Xb} x&w2 ?2ze; L¾Ow 2Y9׷%S1l}y 3넴-΄ 6PN5:Ke@WW>9繨gx4)Z̈h6sF䒈c]$@z/ Gr.Ӧˈ LT&g6m".k^p΀6-#mZL'\rX7-t "1q j1sÒ.}_fD6W\cŘ,IFvS 3bMs)߈K\f.u F<EB޹{}Qu;5tJFPϔjWi܏N`s7+kQ0#%CRiMNjڑ~Y[4'ǫW' _CmTg.|`L4N^VfsP1'NW;qBJNpnrͽ+ަܹG`L*!yL=w24[Z*K\d;fk;z^9rtJfm:Tc(£1TW;#ct sLuz~-B(Q5E㰅# g@tVWzrr 0aD+ LSt?a.K$6#yJi"o-r/C{,><֯b^@ʄad+93ieBJ+ss|=W(u#Y~9PTlK 1%bĄIHG5h(]H1fƌ L*ê";v@v.e(etRNIUW_\W͚2"2fy>Kr繤 vTYp`?6h.Gu}FzS{ul5Z?iOS}=YֱsOg7+[}ٳoʫ Cٜ5աPks1txs]Ёڣf8vCS~2bg24}eGso`շú-Ou){ rO|.;{{X+O2~C~DFlNi6,_/(n3X=Na6'fe{'+S5'{oỚea-%Q}@b (mx7-5_-`FΘhDDSퟀl< c8sSfX9cŁ&Kqr{(V"-~e%f T벲'-r"S(RzZev9=9-DxØ M#,k0ZַUWK`<_PɘK; d(|zמKj̵̯ "]AC AD0AAAC AD0AACAC AD0AAC A AD0AAC AD0AAAC AD0AACAC AD0AAC A AD0AAC AD0A`g|*»R1M6-T ƌ}~%߳OlL: FA 늻=߬YqhV,aK& U0fx@jVOJGVǜ1p=A,/QC lZvӡQQd1N8&@b-uFrwN>0tSfi" qπVi6*tf΀V 2DI`^@|v&L)}T REsKQ (P(߆5w,PODDYNOK583638N=D02rzϯ`Ș'Vޡ6\0fl3v<r` +v FP0<80W,dGD0lo P=ۚ5zw+$#G[S~nL\Ҳn>hb:e۶GHHNG,.iW1+OIf%7M؂Q*:;ЇkskBC)`Ŋ56zdPxlZw=("Ap1玱^?Üͱ030lbGJ䔥gƹsLkW֣x$% P(x1.STfþO`lݑb %3;59]I_;2P{el- @5 Ҏ05{{NoӍq} >RRnTߗN7 Hζ$|! ,v+;!5W|=W%!I0C2a\Y'хot6k | P k/~Hb­k+Lxf3'd$h{L""##npz*7{!;LdtiSٳ: KFQv Nim*tCNw@O6LY3̀)G-iݷxWC gD!woCl IY3$ow~7>Mf4 1fGǰoX.Ox-!??<<. Oi/J.M0~}iOB}ߏfGQ " ` !  " `ыVL+"mQ& 6 cN?Ɨ2S=2\V2S&D䕴K\pAń .+FW~VUJ^IPw:jwd6] {"e¬^ɽN0K,/yd̸r.iq%]fӥEV9aF!)|'eJ80^  1&0$ML̐i1;qʱ0Wt쩸⑎: Okk+4O5_CxeK7 &+؊1we,SdA3Qƫ={c=("R_7`V6F2m{Ħqʜ6>kBl]?NJ5!>w k8cLJK^[0X1's7kZ+2ccӅ+UxG[>T sӷ[i/o,88oGh+3{رuM#ʥ'LlKre@1c,X s}="{bBi }\g̭W ]R_@PNt D9FVttS2  fv"{oKBg?1IS k.=b .i6/>a|sY";0{gԔ؈[n{=V(<3:"1Aܧ#S# bV gL};$4\|d Wv;bq~ /b\5s('aљ?KД1dEq`dc ;l[BV<>9U+YηVj$0 -jGb2 IDAT~x^>hFB! / [0"lD3" Uy]K&Lj˦rRF34Q7 ~Ocm׺~Z+ )czAh܂&PrATɐЂЄtIAAC AD0A(Txjf|1!so^p,EզY%{HP)MNYwMG;0?+,O9[II0>!MMLdyDKƪ)z kIL%ye nA1_Y6융@Cad@Hy&MqC)o<:AZ&<(<jE"G^qY3OĬހg.>JýyN,[5ۨZG̙6TsJm#vTJйӭ9fNA87X|Vky1]ZU/koO#%v2|]H@x.ISpp"{`@Dĩ]"ܞSfFq0RET *D_tA"(\KA;ivR_8>1=9szdLy4@i;%nHP yQ#B=!="[&d̸5Jc`iSPoIF-=r6̸?p"X1jXa.pQ;=6'+yNZff(rcdyTǷr1mwӾ5ga^XQ ފL+({dҽrIi f@ǖE,s#nmӻn"0 Ljaݐ11z}bGn r)LWYMwcvӷt{7GLl,QcR>wj(1n٬)xoxeJ )Hī[G |ǚU}tSeB1[ lI+e2*(s\/0"?YZw{䌞5ӳU 2GR]SSMozÔ% # Y WNxb>$1ܳ3f;#ϲ0mk}ZEd7+Y*]8m;Տze?̡X/l?vvNCid2Ҟ3'd;$__~Ԟt]4&)񶜁^X{zmfq;wC-~H٫Z 8HvA^  AD0AAC AD0AxATp9Cb({Ø}O xərύP&cyJEWu8ƄV0D7$L_vP.IS*&1 s ۱(fv&4s.||:\@m1䖂e ! D'o"J'$kRM?[/DҘ[2glpKۣNZ?PnEN`WD) 鋅!o#9J?kx HI3G8VKAَ$fuHAxSk;azFMGħ #aOƜ'd y#L隑? lRcfl9З6Ħ$32Y1<*{076XA`|Tv Aw*UA8D  Ʃd ! " ` ! k|9Kr#xu2!cPf_(/)RnЍ[K G1ehC-LHueZSCS L*x8|FNMMQ.sk&wo஡ 1!DŽG)FkrFx;~/2wgB90a"`,[0@[ 熀>sUt){9rɤb3*3Mx(eeQfSފ UiNLǣˌo%7S9)w LւN&+4l۠eӍ9 qre>:^ttWw!d"Fx'KWΧ~m+bI%)(2@J>w(ڦ^FdUl4 Zh@" NRx 52Wdd@og@Zt2yLZf] u*-$k>1w2opd{ܴR& H1zW#/$K\(Kk#M=#]e#'ɎFGDŽ;rڤNa)Me=w2@۸.˻ܣMwS~M&;K`ʘDZ9]in _I0< {91!W&{ھ^1;>[E3+VD Ǥ+ҺBJ|FQܟ.);K0fSΝ8ݨUM:7o'[ʓ;Cnf93F89wKn _I0`_C>aq +;+&Lɉ3?iK)ү')}L'9L'W+u{,IePӣ`b-9aGDUcR{ʬ-xꕍ/Ui}3L  xp5;*] yjT>MӖ]?^>0f ?a9&#n5isr" X'uregg&U9է-Vs\kHDke "3hbR0K% S[s"GLhsF : 0~&%M6w<?[Mvub ZgL MU DZ-ɒ,XbŊOhc߱pvм9=D2{[!;VaMc~QТMd[;4q6zN533\OLuIH 9Sxd#h3'« 6wFʊ@a\[qMjNVu #TQϴ2) 5<%E{dxMk%GFTs^6tQ:N껪yӭ z52F U2 ɘrͬ9+3jSo jБr ob_`d 5.`Jl&O- "9 CDx51$7;B֌ O>s9#7Vf_/wW%!#9qRkaՎ9IrKR %ջ`l6 n 9IѼqmX'?x8mN alܛ m:g^k6>3PYxg זVbY}ܕ8xWYÑAjTY鲯e:6Pp  VL*gT\w;ss>O9靲쫥lba uPCƀ*kC[?U(Gwط'`=ȅXb0#GD AD0AAC9kWJWW%S?]D0*MShQI;#ZS8˽g=)#Zc{O:aFV>]|vgL(;}K;ZX3 (خnٕn-+LBN2kRDLY5LП;|H᛼*ۥY5e`J ӛ1UBgD0\0xUض}vm @D2ݘxsߐd93 ;?`AĈCrJf6<.Mu`ݎr@5 Nf= N0dd|f#9s=Yуon`DmѧL_22gҧ7fJ1ҷ:;zodO wtAEŢڄ#h94C= ';aw 9#2px kws)vWJՑ5nd.ENfW[􀹩m36]GjZ22wm+ &3qCG02:$K#DeSPv9_ƒ`'_ljI%ur7E bܥ篾m vRWE GM\0Wn>i3Qc N=n!W@l7Y)973 wRF" 9Y'Ō>W戅y>6arg{袜|{R l[ɯ˒p(]TAF{M12emfMP$P2 ػXPP,kIfim%n(",ũ:`;rΗi ݆ƹ 3q];}a2bs~W ݗ|'nbOzO5&[NW w| # Wh;c1clpr&(5ѽ+XxTJG7HXΚx8 7{l3cM-w *N|n #sm][SӪQ<8sR&_6wƌtPtJ1#C(p%r^ގ-LDM*o.kYbV^&CRmlZ58V;w*xޠ whPmvF0Yp)jO}ɦx`H &䳚rǯ m$fON!>(F:|'ȊE)@^FV /so~L*9>;#>qpΜ`.A:ݷ=R:g¢bCT3[ St~x?>c!)V-Gb%R$!d39P ^# lQ1x3W*}UyBܱu=TbnRC2ܳdf7侖QlY(h9ݡIIWS;!;8MN1=7Y' }R2'x<Χo/uŗ0?1x[P$<ث4TJJ^>N=R w5볠IDAT"b0OW<ӓB.ݐzcHALaZ +e$oAy#7r=9K2#G{Ecu,53]9Gmd ƳUoxTu+G=׬)Y("8˹8]@z\ fj;^)}=Y]$CΖs;W" ȗ&3Zu͜ys;pΔr0qhvecNDΎ5x9 )S˙ Qgt4d 9w`swbJWTVf(9ʼn,8'o̹26]O|c RfH4$-]wck+.:^e> S2B2 ҕvnHLJNHAFrrNb`mgUEɈNмm.FhyKʩX^(&oEw$9NVCqr۳#`"23c S3*'b-AF(c9xRی}>K.`M!1}nlU|.>6Lb_RNuP#<{O=V Hi1dl'c \ɭ^M#$!@tP0Ya, G jx'Q\9 # Oc3c̻wbS=rg0 $c;t ^Okl33ummn_b0"n HUg6SΘԾl ں ~gx?"oxaC |# ,_o4{;Kf3ݱ|m|2Gά6;ĵݩ#ܹ75ŞwxEa0]xG.&iG#v~o^fGB!3=?W׺ѕM]~1g <^y'[fas(-&RK򞑉Aɝ܂$2AC AD0AACx9LD0"4 `("rN$[J C8{yI}‡0 'Җw?(X}s;)6\9)xg-̈́:wo"=|MMQ|~3P4rx\XrK=)t{ dՂ !`~GdȂrw`s&\qr"r.3xQ/,$RV$nڴ \ LI<Prc1N)>! 19Ad) W8k4z٣=Ӄ?TVZkNghtQ:Z?^t_k־Ohgc9v>'$JIRhcsNa='PC֡UӁ|?EDs?g0ʖ7WD(J\ۣI7<̖YvJ\Z^CyYPJuة/M8|#=Qx69Rzx/]JBpprwCN7r*AjhYb%\'&IAĈ9\:β -".i[$gB mK.* I 䒈=vN .h9tbdhIs^mda᧔ R USHTKV*U DW ٓ[3hH{eG4`1uzpǨΧyM# *ចMEgF_[󭺭ݿX+x.$rƤ&e73F\zUL IQk2sF3w Q[KBbjaxRحXjxy<>Brk%~̰rJn};Wljݚٍ,X9Llq}G #D= ~obXf?~Ily?~9cޮ4fӨďLڌaDG?R2lXrm!7,70 5h$u,zWlB0c/E2L80V w>$ɖTE?؍띇&!4;-ȣ[s3Ý%.Ţ/בdA@GZZz2|eA2ȃ~1sۨ=~?Ɨaj$Hqn 2|90|$21K_k Uf{Mĵ74uFȷU 8xˑL6siKgN`es?٭#=]4'b OJOHZ$rS~|l4_\٣aSg5_ %ȟ'W2\͵w_-_I 8zfR| c|d5фk2 kҭS/8$圴V*oϒ,RZd~9e&z/~<+Wۯmx'o'1〔5rβ6}dsu] S`=J]Ƒo: 'A.zKnZS\hȹ$"J|vIEk1rd!R)v 3`8UWr$75甾[Y2Ӛ` pkD71JOQ^"u`J)I8")#Nx/zܢ*P{ #N1J0޲*H8{BN($qVV w}17P |~TRjC(9ŏ\dK8'a֨@{7.`J%jH)y͘n /J%-}#3=8# Ym>]5΂ ^G6Fzy/߫RzŒ*uqjW!v BX4,"xͰI6tyc{0#]h^=h7q{:sa4h3}S9!v[2tС>>]:hia<Ц'|>dH!bb S]t&X0*E6{|`ۂAmjv N4h.rB!Į FlcҭNXmӪn^2^,VG$B`8kѨ#dIQ=ڦAZt )uhHֳ0*hpj, ! b W#DfDଉ kamoh_qIENDB`dov-paps-f4052ca/po/000077500000000000000000000000001437111362100142665ustar00rootroot00000000000000dov-paps-f4052ca/po/Makevars000066400000000000000000000067531437111362100157750ustar00rootroot00000000000000# Makefile variables for PO directory in any package using GNU gettext. # # Copyright (C) 2003-2019 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation gives # unlimited permission to use, copy, distribute, and modify it. # Usually the message domain is the same as the package name. DOMAIN = paps # These two variables depend on the location of this directory. subdir = po top_builddir = .. # These options get passed to xgettext. XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ # This is the copyright holder that gets inserted into the header of the # $(DOMAIN).pot file. Set this to the copyright holder of the surrounding # package. (Note that the msgstr strings, extracted from the package's # sources, belong to the copyright holder of the package.) Translators are # expected to transfer the copyright for their translations to this person # or entity, or to disclaim their copyright. The empty string stands for # the public domain; in this case the translators are expected to disclaim # their copyright. COPYRIGHT_HOLDER = Dov Grobgeld # This tells whether or not to prepend "GNU " prefix to the package # name that gets inserted into the header of the $(DOMAIN).pot file. # Possible values are "yes", "no", or empty. If it is empty, try to # detect it automatically by scanning the files in $(top_srcdir) for # "GNU packagename" string. PACKAGE_GNU = # This is the email address or URL to which the translators shall report # bugs in the untranslated strings: # - Strings which are not entire sentences, see the maintainer guidelines # in the GNU gettext documentation, section 'Preparing Strings'. # - Strings which use unclear terms or require additional context to be # understood. # - Strings which make invalid assumptions about notation of date, time or # money. # - Pluralisation problems. # - Incorrect English spelling. # - Incorrect formatting. # It can be your email address, or a mailing list address where translators # can write to without being subscribed, or the URL of a web page through # which the translators can contact you. MSGID_BUGS_ADDRESS = dov.grobgeld@gmail.com # This is the list of locale categories, beyond LC_MESSAGES, for which the # message catalogs shall be used. It is usually empty. EXTRA_LOCALE_CATEGORIES = # This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt' # context. Possible values are "yes" and "no". Set this to yes if the # package uses functions taking also a message context, like pgettext(), or # if in $(XGETTEXT_OPTIONS) you define keywords with a context argument. USE_MSGCTXT = no # These options get passed to msgmerge. # Useful options are in particular: # --previous to keep previous msgids of translated messages, # --quiet to reduce the verbosity. MSGMERGE_OPTIONS = # These options get passed to msginit. # If you want to disable line wrapping when writing PO files, add # --no-wrap to MSGMERGE_OPTIONS, XGETTEXT_OPTIONS, and # MSGINIT_OPTIONS. MSGINIT_OPTIONS = # This tells whether or not to regenerate a PO file when $(DOMAIN).pot # has changed. Possible values are "yes" and "no". Set this to no if # the POT file is checked in the repository and the version control # program ignores timestamps. PO_DEPENDS_ON_POT = yes # This tells whether or not to forcibly update $(DOMAIN).pot and # regenerate PO files on "make dist". Possible values are "yes" and # "no". Set this to no if the POT file and PO files are maintained # externally. DIST_DEPENDS_ON_UPDATE_PO = yes dov-paps-f4052ca/po/POTFILES.in000066400000000000000000000000141437111362100160360ustar00rootroot00000000000000src/paps.cc dov-paps-f4052ca/scripts/000077500000000000000000000000001437111362100153375ustar00rootroot00000000000000dov-paps-f4052ca/scripts/src-to-paps000077500000000000000000000115701437111362100174410ustar00rootroot00000000000000#!/usr/bin/python ###################################################################### # Use GNU source-hightlight to turn source code into pango markup # and pipe to paps. # # This is currently of limited use for long lines, as the paps/pango # line breaking algorithm will insert hyphens in the text. # # 2023-01-14 Sat # Dov Grobgeld ###################################################################### import argparse import subprocess from pathlib import Path import sys import tempfile def xec(cmd, decode=True, chomp=True, verbose=False): '''Run a command a returns its stdout output. decode -- run (utf8) decode of the resulting string chomp -- get rid of the last newline (like in perl) ''' ph = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE) if verbose: sys.stderr.write(cmd + '\n') res = b'' maxsize = 1024 while True: buf = ph.stdout.read() if len(buf)==0: break res += buf ph.wait() if decode: res=res.decode() if chomp: res = res[:-1] return res def arg_if_not_none(param_name, val): '''Return either an empty string or the parameter with its value''' if val is None: return '' return param_name + ' ' + val + ' ' # Defaults # TBD - Make this a configuration variable pango_outlang_path = '/usr/local/share/paps/pango_markup.outlang' parser = argparse.ArgumentParser(description='Process a file') parser.add_argument('-o', '--output', dest='output', action='store', type=str, default='-', help='Output filename') parser.add_argument('-v', '--verbose', dest='verbose', action='store_true', help='Verbose editing') parser.add_argument('--pango-outlang-path', dest='pango_outlang_path', action='store', type =str, default = pango_outlang_path, help='Path to pango_markup.outlang') parser.add_argument('-s', '--source-lang', dest='source_lang', action='store', type =str, default = None, help='Override the source lang') parser.add_argument('--style-file', dest='style_file', action='store', type =str, default = None, help='Set a style file for syntax highlight') parser.add_argument('--style-css-file', dest='style_css_file', action='store', type =str, default = None, help='Set a style file for syntax highlight') # TBD add additional paps variables, or pass them verbatim parser.add_argument('--columns', dest='columns', action='store', type =int, default = 1, help='Number of columns in paps output') parser.add_argument('--landscape', dest='landscape', action='store_true', help='Output landscape') parser.add_argument('--font', dest='font', action='store', default='', help='Paps font') parser.add_argument('filename', nargs='*', help='Input. Default is stdin') args = parser.parse_args() Output = args.output # Create the pmu file markups = [] for fn in args.filename: source_lang = ({'.py' : 'python', '.cpp' : 'C', '.cxx' : 'C', '.cc' : 'C', '.c' : 'C' }.get(Path(fn).suffix) if args.source_lang is None else args.source_lang) markups.append( xec(f'source-highlight ' + (f'-s {source_lang} ' if source_lang is not None else '') + arg_if_not_none('--style-file', args.style_file) + arg_if_not_none('--style-css-file', args.style_css_file) + f'--outlang-def {args.pango_outlang_path} ' f'--input {fn}', verbose=args.verbose)) with tempfile.TemporaryDirectory() as tmp: pmu_file = Path(tmp) / 'src-to-paps.pmu' with open(pmu_file,'w') as ofh: ofh.write('----'.join(markups)) title =','.join(args.filename) output_args = f'-o {Output} ' if Output!='-' else '' xec(f'paps --header ' f'{"--landscape " if args.landscape else ""}' f'--columns {args.columns} ' f'--separation-lines ' f'--markup ' f'--header-center "{title}" ' + (f' --font "{args.font}" ' if len else "") + f'--header-left "{{now:%c}}" ' f'--header-right="Page {{page_idx}}/{{num_pages}}" ' '--format pdf ' '--wrap=char ' '--show-wrap ' f'{output_args}' f'{pmu_file} ', verbose=args.verbose) dov-paps-f4052ca/src/000077500000000000000000000000001437111362100144375ustar00rootroot00000000000000dov-paps-f4052ca/src/Makefile.am000066400000000000000000000006711437111362100164770ustar00rootroot00000000000000man_MANS = paps.1 bin_PROGRAMS = paps paps_CXXFLAGS = $(WARN_CFLAGS) $(PANGO_CFLAGS) $(FMT_CFLAGS) paps_SOURCES = paps.cc format_from_dict.cc paps_LDADD = $(WARN_LDFLAGS) $(PANGO_LIBS) $(FMT_LIBS) $(lib_LIBRARIES) $(all_libraries) noinst_HEADERS = format_from_dict.h paps_DEPENDENCIES = $(lib_LIBRARIES) AM_CPPFLAGS = -DGETTEXT_PACKAGE='"$(GETTEXT_PACKAGE)"' -DDATADIR='"$(datadir)"' EXTRA_DIST = paps.1 -include $(top_srcdir)/git.mk dov-paps-f4052ca/src/SConstruct000066400000000000000000000006541437111362100164760ustar00rootroot00000000000000env = Environment() env.ParseConfig('pkg-config --cflags --libs pangocairo pangoft2') env.Append(CFLAGS=['-Wall','-g'], CPPDEFINES=['ENABLE_NLS', 'GETTEXT_PACKAGE=\\"paps\\"', 'DATADIR=\\".\\"'], LINKFLAGS=[#'-fsanitize=address', # Use for fsanitize ] ) env.Program('paps', ['paps.cc'], ) dov-paps-f4052ca/src/format_from_dict.cc000066400000000000000000000064071437111362100202730ustar00rootroot00000000000000/* * paps.cc: A postscript printing program using pango. * * Copyright (C) 2002, 2005, 2022 Dov Grobgeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ #include "format_from_dict.h" using namespace std; using namespace fmt; static string scalar_to_string(scalar_t scalar, const string& spec="") { if (holds_alternative(scalar)) { auto val = get(scalar); if (!spec.length()) return val; return format(runtime(format("{{:{}}}", spec)), val); } if (holds_alternative(scalar)) { auto val = get(scalar); if (!spec.length()) return to_string(val); return format(runtime(format("{{:{}}}", spec)), val); } if (holds_alternative(scalar)) { auto val = get(scalar); if (!spec.length()) return to_string(val); return format(runtime(format("{{:{}}}", spec)), val); } if (holds_alternative(scalar)) { time_t val = get(scalar); if (!spec.length()) return to_string(val); return format(runtime(format("{{:{}}}", spec)), fmt::localtime(val)); } throw runtime_error("Unrecognized type!"); // I shouldn't be here! } // Take a python like format string and a dictionary and format // it according to the format string. string format_from_dict(const string& str, dict_t dict) { string res; // Currenly no support for double {{ and double }} int pos=0; size_t len = str.size(); while (true) { size_t start = str.find("{", pos); if (start == string::npos || start == len-1) break; if (str[start+1]=='{') { res += str.substr(pos, start+1); pos = start+1; continue; } size_t end = str.find("}", start); if (end == string::npos) throw runtime_error(format("No end brace for start {{ at {}", start)); if (end < len-1 && str[end+1] == '}') throw runtime_error(format("Can't have double }}}} in formatting clause!", start)); // TBD - fill in res += str.substr(pos, start-pos); string spec = str.substr(start+1, end-start-1); size_t colon_pos = spec.find(":"); if (colon_pos == string::npos) { if (dict.count(spec) == 0) throw runtime_error(format("Can't find {} in dictionary!", spec)); res += scalar_to_string(dict[spec]); } else { // Split on ':' string spec_format = spec.substr(colon_pos+1); spec = spec.substr(0, colon_pos); res += scalar_to_string(dict[spec], spec_format); } pos = end+1; } res += str.substr(pos); return res; } dov-paps-f4052ca/src/format_from_dict.h000066400000000000000000000025261437111362100201330ustar00rootroot00000000000000/* * paps.cc: A postscript printing program using pango. * * Copyright (C) 2002, 2005, 2022 Dov Grobgeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ #ifndef FORMAT_FROM_DICT_H #define FORMAT_FROM_DICT_H #include #include #include #include using scalar_t = std::variant; using dict_t = std::map; // Take a python like format string and a dictionary and format // it according to the format string. std::string format_from_dict(const std::string& str, dict_t dict); #endif /* FORMAT_FROM_DICT */ dov-paps-f4052ca/src/meson.build000066400000000000000000000027141437111362100166050ustar00rootroot00000000000000paps_config = configuration_data() paps_config.set('configure_input', 'paps-config.h file generated by Meson') paps_config.set('PACKAGE', meson.project_name()) paps_config.set('PACKAGE_NAME', 'paps') paps_config.set('PACKAGE_BUGREPORT', 'https://github.com/paps/paps/issues/new') paps_config.set('PAPS_VERSION', meson.project_version()) version_arr = meson.project_version().split('.') paps_config.set('PAPS_MAJOR_VERSION', version_arr[0].to_int()) paps_config.set('PAPS_MINOR_VERSION', version_arr[1].to_int()) paps_config.set('PAPS_MICRO_VERSION', version_arr[2].to_int()) paps_config.set('SIZEOF_INT', cc.sizeof('int')) if cc.get_id() == 'msvc' paps_config.set('PAPS_MSVC_BUILD_PLACEHOLDER', '#define PAPS_BUILT_WITH_MSVC') else paps_config.set('PAPS_MSVC_BUILD_PLACEHOLDER', '#undef PAPS_BUILT_WITH_MSVC') endif #paps_config_h = configure_file(input: files('paps-config.h.in'), # output: 'paps-config.h', # configuration: paps_config, # install_dir: join_paths(get_option('includedir'), 'paps')) paps = executable('paps', ['paps.cc', 'format_from_dict.cc'], c_args: ['-DHAVE_CONFIG_H'], include_directories: incs, dependencies : [pango_dep, cairo_dep, glib_dep, gobject_dep, fmt_dep], install: true) install_man('paps.1') dov-paps-f4052ca/src/paps.1000066400000000000000000000253571437111362100155000ustar00rootroot00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH PAPS 1 "December 20, 2022" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME paps \- text to PostScript converter using Pango .SH SYNOPSIS .B paps .RI [ options ] " files" ... .SH DESCRIPTION .B paps reads an input file and writes a PostScript language or user specified format rendering of the file to standard output. paps accepts international text in any locale and provides internationalized text layout including text shaping and bidirectional text rendering. .P If no filename argument is provided, paps reads the standard input. If the standard input is a terminal, input is terminated by an EOF signal, usually Control-d. .SH OPTIONS .B paps follows the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options is included below. .TP .B \-h, \-\-help Show summary of options. .TP .B \-\-landscape Landscape output. Default is portrait. .TP .B \-\-columns=cl Format output into \fIcl\fR columns. Default is 1. .br Please notice this option isn't related to the terminal length as in a "80 columns terminal". .TP .B \-\-font=desc Use font based on description \fIdesc\fR. Default is \fB"Monospace 12"\fR. The format of the string representation is: .IP "[family-list] [style-options] [size]" .IP where \fIfamily-list\fR is a comma separated list of families optionally terminated by a comma, \fIstyle-options\fR is a whitespace separated list of words where each \fIword\fR describes one of style, variant, weight, or stretch, and \fIsize\fR is a decimal number for size in points, e.g. "Courier,Monospace Bold Italic 10". .TP .B \-o, \-\-output=file Output file. Default is \fBstdout\fR. Output format is set based on \fIfile\fR's extension when \-\-format is not provided. .TP .B \-\-rtl Do right-to-left (RTL) text layout and align text to the right. Text direction is detected automatically. Use this option for explicit RTL layout and right alignment. .TP .B \-\-justify Justify the layout. Stretch complete lines to fill the entire width. .TP .B \-\-wrap=wm Use line wrapping mode \fIwm\fR. Default is \fBword\-char\fR. .IP .sp .ne 2 .mk .na \fBword\fR .ad .RS 18n .rt Wrap lines at word boundaries .RE .IP .sp .ne 3 .mk .na \fBchar\fR .ad .RS 18n .rt Wrap lines at character boundaries .RE .IP .sp .ne 3 .mk .na \fBword-char\fR .ad .RS 18n .rt Wrap lines at word boundaries, but fall back to character boundaries if there is not enough space for a full word .RE .TP .B \-\-show\-wrap Mark wrapped lines with special characters. .TP .B \-\-paper=ps Choose paper size. Accepted paper sizes are 'legal', 'letter', 'A3' and 'A4'. Default is \fBA4\fR. .TP .B \-\-gravity=gr Set base glyph orientation. Default is \fBauto\fR. .IP .sp .ne 3 .mk .na \fBsouth\fR .ad .RS 18n .rt Glyphs stand upright .RE .IP .sp .ne 3 .mk .na \fBeast\fR .ad .RS 18n .rt Glyphs are rotated 90 degrees clockwise .RE .IP .sp .ne 3 .mk .na \fBnorth\fR .ad .RS 18n .rt Glyphs are upside-down .RE .IP .sp .ne 3 .mk .na \fBwest\fR .ad .RS 18n .rt Glyphs are rotated 90 degrees counter-clockwise .RE .IP .sp .ne 3 .mk .na \fBauto\fR .ad .RS 18n .rt Gravity is resolved from the context .RE .TP .B \-\-gravity-hint=gh Set how horizontal scripts behave in a vertical context. Default is \fBnatural\fR. .IP .sp .ne 3 .mk .na \fBnatural\fR .ad .RS 18n .rt Scripts will take their natural gravity based on the base gravity and the script .RE .IP .sp .ne 3 .mk .na \fBstrong\fR .ad .RS 18n .rt Always use the base gravity, regardless of the script .RE .IP .sp .ne 3 .mk .na \fBline\fR .ad .RS 18n .rt For scripts not in their natural direction (e.g. Latin in East gravity), choose per-script gravity such that every script respects the line progression. This means, Latin and Arabic will take opposite gravities and both flow top-to-bottom for example. .RE .TP .B \-\-format=fmt Choose output format. Default is \fBps\fR. .IP .sp .ne 2 .mk .na \fBps\fR .ad .RS 18n .rt PostScript .RE .IP .sp .ne 2 .mk .na \fBpdf\fR .ad .RS 18n .rt Portable Document Format .RE .IP .sp .ne 2 .mk .na \fBsvg\fR .ad .RS 18n .rt Scalable Vector Graphics .RE .TP .B Postscript points Each postscript point equals to 1/72 of an inch. 36 points are 1/2 of an inch. .TP .B \-\-bottom-margin=bm Set bottom margin. Default is 36 postscript points. .TP .B \-\-top-margin=tm Set top margin. Default is 36 postscript points. .TP .B \-\-left-margin=lm Set left margin. Default is 36 postscript points. .TP .B \-\-right-margin=rm Set right margin. Default is 36 postscript points. .TP .B \-\-gutter-width=gw Set gutter width. Default is 40 postscript points. .TP .B \-\-header Draw page header with document name, date and page number for each page. Header is not printed by default. .TP .B \-\-header-left=fmt Sets the formatting for the left side of the header. See FORMAT for an explanation of the header and footer formatting. Default is the current localized date. .TP .B \-\-header-center=fmt Sets the formatting for the center of the header. See FORMAT for an explanation of the header and footer formatting. Default is the filename. .TP .B \-\-header-right=fmt Sets the formatting for the center of the header. See FORMAT for an explanation of the header and footer formatting. Default is the Page number. .TP .B \-\-footer Draw page footer with document name, date and page number for each page. Footer is not printed by default. .TP .B \-\-footer-left=fmt Sets the formatting for the left side of the footer. See FORMAT for an explanation of the footer and footer formatting. The default formatting is an empty string. .TP .B \-\-footer-center=fmt Sets the formatting for the center of the footer. See FORMAT for an explanation of the footer and footer formatting. The default formatting is an empty string. .TP .B \-\-footer-right=fmt Sets the formatting for the center of the footer. See FORMAT for an explanation of the footer and footer formatting. The default formatting is an empty string. .TP .B \-\-title="text" Use \fItext\fR as the title string for page header. By default the input filename or "stdin" is used. .TP .B \-\-markup Interpret input as pango markup. Pango Text Attribute Markup Language allows marking parts of the text with tags defining additional attributes such as font face, size, weight, colors or text decoration such as underline or strikethrough. .TP .B \-\-encoding=enc Assume encoding of the input text is \fIenc\fR. By default the encoding of the current locale is used (e.g. UTF-8). .TP .B \-\-lpi=lines Set number of lines per inch. This determines the line spacing. .TP .B \-\-cpi=chars Set number of characters per inch. This is an alternative method of specifying the font size. .TP .B \-\-g-fatal-warnings Make all glib warnings fatal. .br .SH EXIT STATUS .sp .LP The following exit values are returned: .sp .ne 2 .mk .na \fB0\fR .ad .RS 6n .rt Successful completion. .RE .sp .ne 2 .mk .na \fB1\fR .ad .RS 6n .rt An error occurred. .RE .SH HEADER AND FOOTER FORMATTING .sp .LP The header and footers may be formatted by a mini language based on the python f-strings. Text outside of squiggly brackets are entered literally in the output. Text inside squiggly brackets contain one of the following predefined list of variables: .IP .sp .ne 2 .mk .na \fBnow\fR .ad .RS 18n .rt The current time .RE .IP .sp .ne 2 .mk .na \fBmtime\fR .ad .RS 18n .rt The modification time of the file being printed .RE .IP .sp .ne 2 .mk .na \fBpage_idx\fR .ad .RS 18n .rt The page index of the page .RE .IP .sp .ne 2 .mk .na \fBnum_pages\fR .ad .RS 18n .rt The total number of pages in the document .RE .IP .sp .ne 2 .mk .na \fBfilename\fR .ad .RS 18n .rt The filename (basename) of the document .RE .IP .sp .ne 2 .mk .na \fBpath\fR .ad .RS 18n .rt The full path of the document .RE .SH EXAMPLES .LP \fBExample 1\fR Printing UTF-8 text file .P The following command can be used to print a file in any of the UTF-8 based locales if the file is in UTF-8 or compatible codeset. .sp .in +2 .nf $ \fBpaps en_US_UTF-8.txt\fR .fi .in -2 .LP By default paps will print PostScript rendering to standard output. Send the output to a printer using \fBlp\fR .sp .in +2 .nf $ \fBpaps en_US_UTF-8.txt | lp\fR .fi .in -2 .LP .sp or to a file using redirection or the \fB-o\fR option .sp .in +2 .nf $ \fBpaps en_US_UTF-8.txt > out.ps\fR $ \fBpaps -o out.ps en_US_UTF-8.txt\fR .fi .in -2 .sp .LP .sp .LP \fBExample 2\fR Specify encoding .P To print a file in specific encoding regardless of the current locale setting use the \-\-encoding option. An example for Japanese EUC encoded input file: .sp .in +2 .nf $ \fBpaps --encoding eucjp ja_JP_eucjp.txt > out.ps\fR .fi .in -2 .LP paps will still use current locale setting to prioritize the available fonts for current language. .LP \fBExample 3\fR Specify locale .P Override the \fBLC_ALL\fR environment variable to run paps in a different locale. .sp .in +2 .nf $ \fBLC_ALL=ja_JP.eucjp paps ja_JP_eucjp.txt > out.ps\fR .fi .in -2 .LP Here paps will assume the input is in Japanese EUC encoding and will use Japanese eucjp locale to render the output. If \-\-header is added, the date is printed in Japanese. .LP \fBExample 4\fR Change the header and footer .P Override the header and the footer to show only the page in the middle of the footer. .sp .in +2 .nf $ \fBpaps --separation-lines -o /tmp/foo.pdf --header --header-left='' \\ --header-center='{path}' --header-right='' --footer \\ --footer-left='Printed {now:%c}' \\ --footer-right='Page {page_idx}/{num_pages}' \\ `pwd`/paps.ccx\fR .fi .in -2 .LP Here paps will assume the input is in Japanese EUC encoding and will use Japanese eucjp locale to render the output. If \-\-header is added, the date is printed in Japanese. .SH ENVIRONMENT VARIABLES .B paps uses locale environment variables to determine its behavior. The following categories are used: .sp .ne 2 .mk .na \fBLC_CTYPE\fR .ad .RS 16n .rt to assume the encoding of the input. This can be overridden by \-\-encoding. .RE .sp .ne 2 .mk .na \fBLC_TIME\fR .ad .RS 16n .rt to format the date for header. .RE Font selection is also affected by current locale. Example 3 describes how to run paps in a different locale. .SH SEE ALSO .sp .LP \fBfc\-match\fR(1), \fBsetlocale\fR(3C) .sp .LP .SH AUTHOR paps was written by Dov Grobgeld . .PP This manual page was written by Lior Kaplan , for the Debian project (but may be used by others). dov-paps-f4052ca/src/paps.cc000066400000000000000000001653211437111362100157210ustar00rootroot00000000000000/* Pango * paps.cc: A postscript printing program using pango. * * Copyright (C) 2002, 2005, 2022 Dov Grobgeld * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "format_from_dict.h" #include using namespace std; using namespace fmt; #ifndef _XOPEN_SOURCE #define _XOPEN_SOURCE /* for wcwidth */ // int wcwidth(wchar_t c); #endif #include #if ENABLE_NLS #include #define _(str) gettext(str) #ifdef gettext_noop #define N_(str) gettext_noop(str) #else #define N_(str) (str) #endif #else /* NLS is disabled */ #define _(str) (str) #define N_(str) (str) #endif #define BUFSIZE 1024 #define DEFAULT_FONT_FAMILY "Monospace" #define DEFAULT_FONT_SIZE "12" #define HEADER_FONT_FAMILY "Monospace Bold" #define HEADER_FONT_SCALE "12" #define MAKE_FONT_NAME(f,s) f " " s /* * Cairo sets limit on the comment line for cairo_ps_surface_dsc_comment() to * 255 characters, including the initial percent characters. */ #define CAIRO_COMMENT_MAX 255 #define MARGIN_LEFT 36 #define MARGIN_RIGHT 36 #define MARGIN_TOP 36 #define MARGIN_BOTTOM 36 typedef enum { PAPER_TYPE_A4 = 0, PAPER_TYPE_US_LETTER = 1, PAPER_TYPE_US_LEGAL = 2, PAPER_TYPE_A3 = 3 } paper_type_t ; typedef enum { FORMAT_POSTSCRIPT = 0, FORMAT_PDF = 1, FORMAT_SVG = 2 } output_format_t ; typedef struct { double width; double height; } paper_size_t; static const paper_size_t paper_sizes[] = { { 595.28, 841.89}, /* A4 */ { 612, 792}, /* US letter */ { 612, 1008}, /* US legal */ { 842, 1190} /* A3 */ }; struct PageLayout { ~PageLayout() { }; int column_width; int column_height; int num_columns; int gutter_width; /* These are all in postscript points=1/72 inch... */ int top_margin; int bottom_margin; int left_margin; int right_margin; int num_pages; double page_width; double page_height; int header_ypos; int header_sep; int header_height; int footer_height; paper_type_t paper_type; gdouble scale_x; gdouble scale_y; bool do_draw_header; bool do_draw_footer; bool do_duplex; bool do_tumble; bool do_landscape; bool do_justify; bool do_show_hyphens; bool do_draw_separation_line; bool do_draw_contour; bool do_show_wrap; bool do_use_markup; bool do_stretch_chars; PangoDirection pango_dir; string title; string filename_path; string filename; char* header_left = nullptr; char* header_center = nullptr; char* header_right = nullptr; char* footer_left = nullptr; char* footer_center = nullptr; char* footer_right = nullptr; string header_font_desc; gdouble lpi; gdouble cpi; dict_t document_info; }; struct LineLink { PangoLayoutLine *pango_line; PangoRectangle logical_rect; PangoRectangle ink_rect; int formfeed; bool wrapped; // Whether the paragraph was character wrapped }; typedef struct _Paragraph Paragraph; /* Structure representing a paragraph */ struct _Paragraph { const char *text; int length; int height; /* Height, in pixels */ int formfeed; bool wrapped; bool clipped; // Whether the line was clipped. Used for CPI. PangoLayout *layout; }; /* Information passed in user data when drawing outlines */ static GList *split_paragraphs_into_lines (PageLayout *page_layout, GList *paragraphs); static char *read_file (FILE *file, gchar *encoding); static GList *split_text_into_paragraphs (PangoContext *pango_context, PageLayout *page_layout, int paint_width, const char *text); static int output_pages (cairo_surface_t * surface, cairo_t *cr, GList *pango_lines, PageLayout *page_layout, PangoContext *pango_context); static void eject_column (cairo_t *cr, double title_height, PageLayout *page_layout, int column_idx, bool measure_only); static void eject_page (cairo_t *cr); static void start_page (cairo_surface_t *surface, cairo_t *cr, PageLayout *page_layout, bool measure_only); static void draw_line_to_page (cairo_t *cr, int column_idx, int column_pos, PageLayout *page_layout, PangoLayoutLine *line, bool draw_wrap_character); static int draw_page_header_line_to_page(cairo_t *cr, bool is_footer, PageLayout *page_layout, PangoContext *ctx, int page, int num_pages, dict_t& document_info, bool measure_only); static void postscript_dsc_comments (cairo_surface_t *surface, PageLayout *page_layout); static void build_document_info (PageLayout* page_layout, dict_t& document_info); bool copy_pango_parse_enum (GType type, const char *str, int *value, bool warn, char **possible_values); static char* get_encoding(void); string get_date(); string fn_basename(const string& filename); FILE *output_fh; static paper_type_t paper_type = PAPER_TYPE_A4; static bool output_format_set = false; static output_format_t output_format = FORMAT_POSTSCRIPT; static PangoGravity gravity = PANGO_GRAVITY_AUTO; static PangoGravityHint gravity_hint = PANGO_GRAVITY_HINT_NATURAL; static PangoWrapMode opt_wrap = PANGO_WRAP_WORD_CHAR; static cairo_font_face_t *paps_glyph_face = NULL; /* Special face for paps characters, e.g. newline */ static double glyph_font_size = -1; /* Render function for paps glyphs */ static cairo_status_t paps_render_glyph(cairo_scaled_font_t *scaled_font G_GNUC_UNUSED, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *extents) { char ch = (unsigned char)glyph; if (ch == 'R' || ch == 'L') { // A newline sign that I created with MetaPost cairo_save(cr); cairo_scale(cr,0.005,-0.005); // TBD - figure out the scaling. if (ch == 'L') { cairo_scale(cr,-1,1); // cairo_translate(cr,-120,0); // Keep glyph protruding to the right. } cairo_translate(cr, 20,-50); cairo_move_to(cr, 0, 175); cairo_curve_to(cr, 25.69278, 175, 53.912, 177.59557, 71.25053, 158.75053); cairo_curve_to(cr, 103.52599, 123.67075, 64.54437, 77.19373, 34.99985, 34.99985); cairo_set_line_width(cr, 25); cairo_stroke(cr); cairo_move_to(cr,0,0); cairo_line_to(cr,75,0); cairo_line_to(cr,0,75); cairo_close_path(cr); cairo_fill(cr); cairo_restore(cr); } return CAIRO_STATUS_SUCCESS; } static bool _paps_arg_paper_cb(const char *option_name, const char *value, gpointer data) { bool retval = true; if (value && *value) { if (g_ascii_strcasecmp(value, "legal") == 0) paper_type = PAPER_TYPE_US_LEGAL; else if (g_ascii_strcasecmp(value, "letter") == 0) paper_type = PAPER_TYPE_US_LETTER; else if (g_ascii_strcasecmp(value, "a4") == 0) paper_type = PAPER_TYPE_A4; else if (g_ascii_strcasecmp(value, "a3") == 0) paper_type = PAPER_TYPE_A3; else { retval = false; fprintf(stderr, _("Unknown page size name: %s.\n"), value); } } else { fprintf(stderr, _("You must specify page size.\n")); retval = false; } return retval; } static bool parse_int (const char *word, int *out) { char *end; long val; int i; if (word == NULL) return false; val = strtol (word, &end, 10); i = val; if (end != word && *end == '\0' && val >= 0 && val == i) { if (out) *out = i; return true; } return false; } // A local copy of the deprecated pango_parse_enum. bool copy_pango_parse_enum (GType type, const char *str, int *value, bool warn, char **possible_values) { GEnumClass *klass = nullptr; bool ret = true; GEnumValue *v = nullptr; klass = (GEnumClass*)g_type_class_ref (type); if (G_LIKELY (str)) v = g_enum_get_value_by_nick (klass, str); if (v) { if (G_LIKELY (value)) *value = v->value; } else if (!parse_int (str, value)) { ret = false; if (G_LIKELY (warn || possible_values)) { int i; GString *s = g_string_new (nullptr); for (i = 0, v = g_enum_get_value (klass, i); v; i++ , v = g_enum_get_value (klass, i)) { if (i) g_string_append_c (s, '/'); g_string_append (s, v->value_nick); } if (warn) g_warning ("%s must be one of %s", G_ENUM_CLASS_TYPE_NAME(klass), s->str); if (possible_values) *possible_values = s->str; g_string_free (s, possible_values ? false : true); } } g_type_class_unref (klass); return ret; } static bool parse_enum (GType type, int *value, const char *name, const char *arg, gpointer data G_GNUC_UNUSED, GError **error) { char *possible_values = nullptr; bool ret; ret = copy_pango_parse_enum (type, arg, value, false, &possible_values); if (!ret && error) { g_set_error(error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, _("Argument for %1$s must be one of %2$s"), name, possible_values); } g_free (possible_values); return ret; } static bool parse_wrap (const char *name, const char *arg, gpointer data, GError **error) { return (parse_enum (PANGO_TYPE_WRAP_MODE, (int*)(void*)&opt_wrap, name, arg, data, error)); } static bool parse_gravity_hint (const char *name, const char *arg, gpointer data, GError **error) { return (parse_enum (PANGO_TYPE_GRAVITY_HINT, (int*)(void*)&gravity_hint, name, arg, data, error)); } static bool parse_gravity (const char *name, const char *arg, gpointer data, GError **error) { return (parse_enum (PANGO_TYPE_GRAVITY, (int*)(void*)&gravity, name, arg, data, error)); } static bool _paps_arg_format_cb(const char *option_name, const char *value, gpointer data) { bool retval = true; if (value && *value) { output_format_set = true; if (g_ascii_strcasecmp(value, "pdf") == 0) output_format = FORMAT_PDF; else if (g_ascii_strcasecmp(value, "ps") == 0 || g_ascii_strcasecmp(value, "postscript") == 0) output_format = FORMAT_POSTSCRIPT; else if (g_ascii_strcasecmp(value, "svg") == 0) output_format = FORMAT_SVG; else { retval = false; fprintf(stderr, _("Unknown output format: %s.\n"), value); } } else { fprintf(stderr, _("You must specify a output format.\n")); retval = false; } return retval; } static bool _paps_arg_lpi_cb(const gchar *option_name, const gchar *value, gpointer data) { bool retval = true; gchar *p = nullptr; PageLayout *page_layout = (PageLayout*)data; if (value && *value) { errno = 0; page_layout->lpi = g_strtod(value, &p); if ((p && *p) || errno == ERANGE) { fprintf(stderr, _("Given LPI value was invalid.\n")); retval = false; } } else { fprintf(stderr, _("You must specify the amount of lines per inch.\n")); retval = false; } return retval; } static bool _paps_arg_cpi_cb(const gchar *option_name, const gchar *value, gpointer data) { bool retval = true; gchar *p = nullptr; PageLayout *page_layout = (PageLayout*)data; if (value && *value) { errno = 0; page_layout->cpi = g_strtod(value, &p); if ((p && *p) || errno == ERANGE) { fprintf(stderr, _("Given CPI value was invalid.\n")); retval = false; } } else { fprintf(stderr, _("You must specify the amount of characters per inch.\n")); retval = false; } return retval; } /* * Return codeset name of the environment's locale. Use UTF8 by default */ static char* get_encoding(void) { static char *encoding = nullptr; if (encoding == nullptr) encoding = nl_langinfo(CODESET); return encoding; } static cairo_status_t paps_cairo_write_func(void *closure G_GNUC_UNUSED, const unsigned char *data, unsigned int length) { fwrite(data,length,1,output_fh); return CAIRO_STATUS_SUCCESS; } int main(int argc, char *argv[]) { gboolean do_landscape = false, do_rtl = false, do_justify = false, do_show_hyphens=false, do_draw_header = false, do_draw_footer=false; gboolean do_stretch_chars = false; gboolean do_draw_separation_line = false; gboolean do_use_markup = false; gboolean do_show_wrap = false; /* Whether to show wrap characters */ gboolean do_show_version = false; // Show version and exit int num_columns = 1; int top_margin = MARGIN_TOP, bottom_margin = MARGIN_BOTTOM, right_margin = MARGIN_RIGHT, left_margin = MARGIN_LEFT; int gutter_width = 40; gboolean do_fatal_warnings = false; const gchar *font = MAKE_FONT_NAME (DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE); gchar *encoding = nullptr; gchar *output = nullptr; gchar *htitle = nullptr; gchar *header_left = nullptr; gchar *header_center = nullptr; gchar *header_right = nullptr; gchar *footer_left = nullptr; gchar *footer_center = nullptr; gchar *footer_right = nullptr; PageLayout page_layout; GOptionContext *ctxt = g_option_context_new("[text file]"); GOptionEntry entries[] = { {"landscape", 0, 0, G_OPTION_ARG_NONE, &do_landscape, N_("Landscape output. (Default: portrait)"), nullptr}, {"columns", 0, 0, G_OPTION_ARG_INT, &num_columns, N_("Number of columns output. (Default: 1)"), "NUM"}, {"font", 0, 0, G_OPTION_ARG_STRING, &font, N_("Set font. (Default: Monospace 12)"), "DESC"}, {"output", 'o', 0, G_OPTION_ARG_STRING, &output, N_("Output file. (Default: stdout)"), "DESC"}, {"version", 'v', 0, G_OPTION_ARG_NONE, &do_show_version, N_("Current version."), nullptr}, {"rtl", 0, 0, G_OPTION_ARG_NONE, &do_rtl, N_("Do right-to-left text layout."), nullptr}, {"separation-lines", 0, 0, G_OPTION_ARG_NONE, &do_draw_separation_line, N_("Do draw separation lines between columns and headers and footers."), nullptr}, {"justify", 0, 0, G_OPTION_ARG_NONE, &do_justify, N_("Justify the layout."), nullptr}, {"hyphens", 0, 0, G_OPTION_ARG_NONE, &do_show_hyphens, N_("Show hyphens when wrapping."), nullptr}, {"wrap", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)&parse_wrap, N_("Text wrapping mode [word, char, word-char]. (Default: word-char)"), "WRAP"}, {"show-wrap", 0, 0, G_OPTION_ARG_NONE, &do_show_wrap, N_("Show characters for wrapping."), nullptr}, {"paper", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)_paps_arg_paper_cb, N_("Set paper size [legal, letter, a3, a4]. (Default: a4)"), "PAPER"}, {"gravity", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)&parse_gravity, N_("Base glyph rotation [south, west, north, east, auto]. (Defaut: auto)"), "GRAVITY"}, {"gravity-hint", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)&parse_gravity_hint, N_("Base glyph orientation [natural, strong, line]. (Default: natural)"), "HINT"}, {"format", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)_paps_arg_format_cb, N_("Set output format [pdf, svg, ps]. (Default: ps)"), "FORMAT"}, {"bottom-margin", 0, 0, G_OPTION_ARG_INT, &bottom_margin, N_("Set bottom margin in postscript point units (1/72 inch). (Default: 36)"), "NUM"}, {"top-margin", 0, 0, G_OPTION_ARG_INT, &top_margin, N_("Set top margin. (Default: 36)"), "NUM"}, {"right-margin", 0, 0, G_OPTION_ARG_INT, &right_margin, N_("Set right margin. (Default: 36)"), "NUM"}, {"left-margin", 0, 0, G_OPTION_ARG_INT, &left_margin, N_("Set left margin. (Default: 36)"), "NUM"}, {"gutter-width", 0, 0, G_OPTION_ARG_INT, &gutter_width, N_("Set gutter width. (Default: 40)"), "NUM"}, {"header", 0, 0, G_OPTION_ARG_NONE, &do_draw_header, N_("Draw page header for each page."), nullptr}, {"footer", 0, 0, G_OPTION_ARG_NONE, &do_draw_footer, "Draw page footer for each page.", nullptr}, {"title", 0, 0, G_OPTION_ARG_STRING, &htitle, N_("Title string for page header (Default: filename/stdin)."), "TITLE"}, {"header-left", 0, 0, G_OPTION_ARG_STRING, &header_left, N_("Left side of the header. Default is localized date."), "HEADER_LEFT"}, {"header-center", 0, 0, G_OPTION_ARG_STRING, &header_center, N_("Center side of the header. Default is localized date."), "HEADER_CENTER"}, {"header-right", 0, 0, G_OPTION_ARG_STRING, &header_right, N_("Right side of the header. Default is localized date."), "HEADER_RIGHT"}, {"footer-left", 0, 0, G_OPTION_ARG_STRING, &footer_left, N_("Left side of the footer. Default is localized date."), "FOOTER_LEFT"}, {"footer-center", 0, 0, G_OPTION_ARG_STRING, &footer_center, N_("Center side of the footer. Default is localized date."), "FOOTER_CENTER"}, {"footer-right", 0, 0, G_OPTION_ARG_STRING, &footer_right, N_("Right side of the footer. Default is localized date."), "FOOTER_RIGHT"}, {"markup", 0, 0, G_OPTION_ARG_NONE, &do_use_markup, N_("Interpret input text as pango markup."), nullptr}, {"encoding", 0, 0, G_OPTION_ARG_STRING, &encoding, N_("Assume encoding of input text. (Default: UTF-8)"), "ENCODING"}, {"lpi", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)_paps_arg_lpi_cb, N_("Set the amount of lines per inch."), "REAL"}, {"cpi", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer)_paps_arg_cpi_cb, N_("Set the amount of characters per inch."), "REAL"}, /* * not fixed for cairo backend: disable * {"stretch-chars", 0, 0, G_OPTION_ARG_NONE, &do_stretch_chars, N_("Stretch characters in y-direction to fill lines."), nullptr}, */ {"g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &do_fatal_warnings, N_("Make all glib warnings fatal."), "REAL"}, {nullptr} }; GError *error = nullptr; FILE *IN = nullptr; GList *paragraphs; GList *pango_lines; PangoContext *pango_context; PangoFontDescription *font_description; PangoDirection pango_dir = PANGO_DIRECTION_LTR; PangoFontMap *fontmap; PangoFontset *fontset; PangoFontMetrics *metrics; int total_gutter_width; double page_width = paper_sizes[0].width; double page_height = paper_sizes[0].height; int do_tumble = -1; /* -1 means not initialized */ int do_duplex = -1; const gchar *header_font_desc = MAKE_FONT_NAME (HEADER_FONT_FAMILY, HEADER_FONT_SCALE); const gchar *filename_in; gchar *text; /* int header_sep = 20; */ int max_width = 0, w; GOptionGroup *options; cairo_t *cr; cairo_surface_t *surface = nullptr; double surface_page_width = 0, surface_page_height = 0; /* Set locale from environment */ (void) setlocale(LC_ALL, ""); /* Setup i18n */ textdomain(GETTEXT_PACKAGE); bindtextdomain(GETTEXT_PACKAGE, DATADIR "/locale"); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); /* Setup the paps glyph face */ paps_glyph_face = cairo_user_font_face_create(); cairo_user_font_face_set_render_glyph_func(paps_glyph_face, paps_render_glyph); /* Init PageLayout parameters set by the option parsing */ page_layout.cpi = page_layout.lpi = 0.0L; options = g_option_group_new("main","","",&page_layout, nullptr); g_option_group_add_entries(options, entries); g_option_group_set_translation_domain(options, GETTEXT_PACKAGE); g_option_context_set_main_group(ctxt, options); #if 0 g_option_context_add_main_entries(ctxt, entries, nullptr); #endif /* Parse command line */ if (!g_option_context_parse(ctxt, &argc, &argv, &error)) { fprintf(stderr, _("Command line error: %s\n"), error->message); exit(1); } if (do_show_version) { printf("Version: %s\n", PACKAGE_STRING); exit(0); } if (do_fatal_warnings) g_log_set_always_fatal(G_LOG_LEVEL_MASK); if (do_rtl) pango_dir = PANGO_DIRECTION_RTL; page_layout.header_left = header_left; page_layout.header_center = header_center; page_layout.header_right = header_right; page_layout.footer_left = footer_left; page_layout.footer_center = footer_center; page_layout.footer_right = footer_right; page_layout.do_draw_header = do_draw_header; page_layout.do_draw_footer = do_draw_footer; if (argc > 1) { filename_in = argv[1]; IN = fopen(filename_in, "r"); if (!IN) { fprintf(stderr, _("Failed to open %s!\n"), filename_in); exit(1); } } else { filename_in = "stdin"; IN = stdin; } // For now always write to stdout if (output == nullptr) output_fh = stdout; else { output_fh = fopen(output,"wb"); if (!output_fh) { fprintf(stderr, _("Failed to open %s for writing!\n"), output); exit(1); } } /* Page layout */ page_width = paper_sizes[(int)paper_type].width; page_height = paper_sizes[(int)paper_type].height; /* Deduce output format from file name if not explicitely set */ if (!output_format_set && output != nullptr) { if (g_str_has_suffix(output, ".svg") || g_str_has_suffix(output, ".SVG")) output_format = FORMAT_SVG; else if (g_str_has_suffix(output, ".pdf") || g_str_has_suffix(output, ".PDF")) output_format = FORMAT_PDF; /* Otherwise keep postscript default */ } /* Swap width and height for landscape except for postscript */ surface_page_width = page_width; surface_page_height = page_height; if (output_format != FORMAT_POSTSCRIPT && do_landscape) { surface_page_width = page_height; surface_page_height = page_width; } if (output_format == FORMAT_POSTSCRIPT) surface = cairo_ps_surface_create_for_stream(&paps_cairo_write_func, nullptr, surface_page_width, surface_page_height); else if (output_format == FORMAT_PDF) surface = cairo_pdf_surface_create_for_stream(&paps_cairo_write_func, nullptr, surface_page_width, surface_page_height); else surface = cairo_svg_surface_create_for_stream(&paps_cairo_write_func, nullptr, surface_page_width, surface_page_height); cr = cairo_create(surface); pango_context = pango_cairo_create_context(cr); pango_cairo_context_set_resolution(pango_context, 72.0); /* Native postscript resolution */ /* Setup pango */ pango_context_set_base_dir (pango_context, pango_dir); pango_context_set_language (pango_context, pango_language_get_default ()); pango_context_set_base_gravity (pango_context, gravity); pango_context_set_gravity_hint (pango_context, gravity_hint); /* create the font description */ font_description = pango_font_description_from_string (font); if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_FAMILY) == 0) pango_font_description_set_family (font_description, DEFAULT_FONT_FAMILY); if ((pango_font_description_get_set_fields (font_description) & PANGO_FONT_MASK_SIZE) == 0) pango_font_description_set_size (font_description, atoi(DEFAULT_FONT_SIZE) * PANGO_SCALE); // Keep the font size for the wrap character. glyph_font_size = pango_font_description_get_size(font_description) / PANGO_SCALE; pango_context_set_font_description (pango_context, font_description); if (num_columns <= 0) { fprintf(stderr, _("%s: Invalid input: --columns=%d, using default.\n"), g_get_prgname (), num_columns); num_columns = 1; } if (num_columns == 1) total_gutter_width = 0; else total_gutter_width = gutter_width * (num_columns - 1); if (do_landscape) { double tmp; tmp = page_width; page_width = page_height; page_height = tmp; if (do_tumble < 0) do_tumble = true; if (do_duplex < 0) do_duplex = true; } else { if (do_tumble < 0) do_tumble = true; if (do_duplex < 0) do_duplex = true; } page_layout.page_width = page_width; page_layout.page_height = page_height; page_layout.paper_type = paper_type; page_layout.num_columns = num_columns; page_layout.left_margin = left_margin; page_layout.right_margin = right_margin; page_layout.gutter_width = gutter_width; page_layout.top_margin = top_margin; page_layout.bottom_margin = bottom_margin; page_layout.header_ypos = page_layout.top_margin; page_layout.header_height = 0; page_layout.footer_height = 0; page_layout.do_show_wrap = do_show_wrap; page_layout.scale_x = 1.0L; page_layout.scale_y = 1.0L; page_layout.header_sep = 0; // header_sep; page_layout.column_height = (int)page_height - page_layout.top_margin - page_layout.header_sep - page_layout.bottom_margin; page_layout.column_width = ((int)page_layout.page_width - page_layout.left_margin - page_layout.right_margin - total_gutter_width) / page_layout.num_columns; page_layout.do_draw_separation_line = do_draw_separation_line; page_layout.do_landscape = do_landscape; page_layout.do_justify = do_justify; page_layout.do_show_hyphens = do_show_hyphens; page_layout.do_stretch_chars = do_stretch_chars; page_layout.do_use_markup = do_use_markup; page_layout.do_tumble = do_tumble; page_layout.do_duplex = do_duplex; page_layout.pango_dir = pango_dir; page_layout.filename_path = filename_in; page_layout.filename = fn_basename(filename_in); if (htitle) page_layout.title = htitle; else page_layout.title = fn_basename(filename_in); page_layout.header_font_desc = header_font_desc; /* calculate x-coordinate scale */ if (page_layout.cpi > 0.0L) { gint font_size; fontmap = pango_ft2_font_map_new (); fontset = pango_font_map_load_fontset (fontmap, pango_context, font_description, pango_language_get_default()); metrics = pango_fontset_get_metrics (fontset); max_width = pango_font_metrics_get_approximate_char_width (metrics); w = pango_font_metrics_get_approximate_digit_width (metrics); if (w > max_width) max_width = w; page_layout.scale_x = 1.0L / page_layout.cpi * 72.0 * (gdouble)PANGO_SCALE / (gdouble)max_width; pango_font_metrics_unref (metrics); g_object_unref (G_OBJECT (fontmap)); font_size = pango_font_description_get_size (font_description); // update the font size to that width pango_font_description_set_size (font_description, (int)(font_size * page_layout.scale_x)); glyph_font_size = font_size * page_layout.scale_x / PANGO_SCALE; pango_context_set_font_description (pango_context, font_description); } page_layout.scale_x = page_layout.scale_y = 1.0; if (encoding == nullptr) encoding = get_encoding(); text = read_file(IN, encoding); if (output_format == FORMAT_POSTSCRIPT) postscript_dsc_comments(surface, &page_layout); paragraphs = split_text_into_paragraphs(pango_context, &page_layout, page_layout.column_width, text); pango_lines = split_paragraphs_into_lines(&page_layout, paragraphs); cairo_scale(cr, page_layout.scale_x, page_layout.scale_y); output_pages(surface, cr, pango_lines, &page_layout, pango_context); cairo_destroy (cr); cairo_surface_finish (surface); cairo_surface_destroy(surface); g_option_context_free(ctxt); return 0; } /* Read an entire file into a string */ static char * read_file (FILE *file, gchar *encoding) { GString *inbuf; char *text; char buffer[BUFSIZE]; GIConv cvh = nullptr; gsize inc_seq_bytes = 0; if (encoding != nullptr) { cvh = g_iconv_open ("UTF-8", encoding); if (cvh == (GIConv)-1) { fprintf(stderr, _("%s: Invalid encoding: %s\n"), g_get_prgname (), encoding); exit(1); } } inbuf = g_string_new (nullptr); while (1) { char *ib, *ob, obuffer[BUFSIZE * 6], *bp; gsize iblen, oblen; bp = fgets (buffer+inc_seq_bytes, BUFSIZE-inc_seq_bytes-1, file); if (inc_seq_bytes) inc_seq_bytes = 0; if (ferror (file)) { fprintf(stderr, _("%s: Error reading file.\n"), g_get_prgname ()); g_string_free (inbuf, true); exit(1); } else if (bp == nullptr) break; if (cvh != nullptr) { ib = buffer; iblen = strlen (ib); ob = bp = obuffer; oblen = BUFSIZE * 6 - 1; if (g_iconv (cvh, &ib, &iblen, &ob, &oblen) == (gsize)-1) { /* * EINVAL - incomplete sequence at the end of the buffer. Move the * incomplete sequence bytes to the beginning of the buffer for * the next round of conversion. */ if (errno == EINVAL) { inc_seq_bytes = iblen; memmove (buffer, ib, inc_seq_bytes); } else { fprintf (stderr, _("%1$s: Error while converting input from '%2$s' to UTF-8.\n"), g_get_prgname(), encoding); exit(1); } } obuffer[BUFSIZE * 6 - 1 - oblen] = 0; } g_string_append (inbuf, bp); } fclose (file); /* Add a trailing new line if it is missing */ if (inbuf->len && inbuf->str[inbuf->len-1] != '\n') g_string_append(inbuf, "\n"); text = inbuf->str; g_string_free (inbuf, false); if (encoding != nullptr && cvh != nullptr) g_iconv_close(cvh); return text; } // Turn off the use of hyphens static void layout_turn_off_hyphens(PangoLayout *layout) { // Request not to get any hypens PangoAttrList *attrs = pango_layout_get_attributes(layout); if (attrs == NULL) attrs = pango_attr_list_new (); pango_attr_list_insert(attrs, pango_attr_insert_hyphens_new(FALSE)); pango_layout_set_attributes (layout, attrs); } /* Take a UTF8 string and break it into paragraphs on \n characters */ static GList * split_text_into_paragraphs (PangoContext *pango_context, PageLayout *page_layout, int paint_width, /* In pixels */ const char *text) { const char *p = text; char *next; gunichar wc; GList *result = nullptr; const char *last_para = text; /* If we are using markup we treat the entire text as a single paragraph. * I tested it and found that this is much slower than the split and * assign method used below. Otherwise we might as well use this single * chunk method always. * * I don't think we need this at all, and are better of reading one * line at a time... */ #if 0 if (0 && page_layout->do_use_markup) { Paragraph *para = g_new (Paragraph, 1); para->wrapped = false; /* No wrapped chars for markups */ para->clipped = false; para->text = text; para->length = strlen(text); para->layout = pango_layout_new (pango_context); pango_layout_set_attributes (para->layout, attrs); pango_layout_set_markup (para->layout, para->text, para->length); pango_layout_set_justify (para->layout, page_layout->do_justify); pango_layout_set_alignment (para->layout, page_layout->pango_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); pango_layout_set_wrap (para->layout, opt_wrap); para->height = 0; result = g_list_prepend (result, para); } else #endif { while (p != nullptr && *p) { wc = g_utf8_get_char (p); next = g_utf8_next_char (p); if (wc == (gunichar)-1) { fprintf (stderr, _("%s: Invalid character in input\n"), g_get_prgname ()); wc = 0; } if (!*p || !wc || wc == '\r' || wc == '\n' || wc == '\f') { Paragraph *para = g_new (Paragraph, 1); para->wrapped = false; para->clipped = false; para->text = last_para; para->length = p - last_para; /* handle dos line breaks */ if (wc == '\r' && *next == '\n') next = g_utf8_next_char(next); para->layout = pango_layout_new (pango_context); if (page_layout->cpi > 0.0L) { /* figuring out the correct width from the pango_font_metrics_get_approximate_width() * is really hard and pango_layout_set_wrap() doesn't work properly then. * Those are not reliable to render the characters exactly according to the given CPI. * So re-calculate the width to wrap up to be comfortable with CPI. */ wchar_t *wtext = nullptr, *wnewtext = nullptr; gchar *newtext = nullptr; gsize len, col, i, wwidth = 0; PangoRectangle ink_rect, logical_rect; wtext = (wchar_t *)g_utf8_to_ucs4 (para->text, para->length, nullptr, nullptr, nullptr); if (wtext == nullptr) { fprintf (stderr, _("%s: Unable to convert UTF-8 to UCS-4.\n"), g_get_prgname ()); fail: g_free (wtext); g_free (wnewtext); g_free (newtext); exit (1); } len = g_utf8_strlen (para->text, para->length); /* the amount of characters that can be put on the line against CPI */ col = (int)(page_layout->column_width / 72.0 * page_layout->cpi); if (len > col) { /* need to wrap them up */ wnewtext = g_new (wchar_t, wcslen (wtext) + 1); para->clipped = true; if (wnewtext == nullptr) { fprintf (stderr, _("%s: Unable to allocate the memory.\n"), g_get_prgname ()); goto fail; } for (i = 0; i < len; i++) { gssize w = wcwidth (wtext[i]); if (w >= 0) wwidth += w; if (wwidth > col) break; wnewtext[i] = wtext[i]; } wnewtext[i] = 0L; newtext = g_ucs4_to_utf8 ((const gunichar *)wnewtext, i, nullptr, nullptr, nullptr); if (newtext == nullptr) { fprintf (stderr, _("%s: Unable to convert UCS-4 to UTF-8.\n"), g_get_prgname ()); goto fail; } if (page_layout->do_use_markup) pango_layout_set_markup (para->layout, newtext, -1); else pango_layout_set_text (para->layout, newtext, -1); // Request not to get any hypens if (!page_layout->do_show_hyphens) layout_turn_off_hyphens(para->layout); pango_layout_get_extents (para->layout, &ink_rect, &logical_rect); paint_width = logical_rect.width / PANGO_SCALE; g_free (wnewtext); g_free (newtext); para->length = i; next = g_utf8_offset_to_pointer (para->text, para->length); wc = g_utf8_get_char (g_utf8_prev_char (next)); } else { pango_layout_set_text (para->layout, para->text, para->length); } g_free (wtext); pango_layout_set_width (para->layout, -1); } else { if (page_layout->do_use_markup) pango_layout_set_markup (para->layout, para->text, para->length); else pango_layout_set_text (para->layout, para->text, para->length); pango_layout_set_width (para->layout, paint_width * PANGO_SCALE); pango_layout_set_wrap (para->layout, opt_wrap); if (!page_layout->do_show_hyphens) layout_turn_off_hyphens(para->layout); if (opt_wrap == PANGO_WRAP_CHAR) para->wrapped = true; /* Should we support truncation as well? */ } pango_layout_set_justify (para->layout, page_layout->do_justify); pango_layout_set_alignment (para->layout, page_layout->pango_dir == PANGO_DIRECTION_LTR ? PANGO_ALIGN_LEFT : PANGO_ALIGN_RIGHT); para->height = 0; last_para = next; if (wc == '\f') para->formfeed = 1; else para->formfeed = 0; result = g_list_prepend (result, para); } if (!wc) /* incomplete character at end */ break; p = next; } } return g_list_reverse (result); } /* Split a list of paragraphs into a list of lines. */ GList * split_paragraphs_into_lines(PageLayout *page_layout, GList *paragraphs) { GList *line_list = nullptr; int max_height = 0; /* Read the file */ /* Now split all the pagraphs into lines */ GList *par_list; par_list = paragraphs; while(par_list) { int para_num_lines, i; LineLink *line_link; Paragraph *para = (Paragraph*)par_list->data; para_num_lines = pango_layout_get_line_count(para->layout); for (i=0; iformfeed = 0; line_link->wrapped = (para->wrapped && i < para_num_lines - 1) || (para->clipped); line_link->pango_line = pango_layout_get_line(para->layout, i); pango_layout_line_get_extents(line_link->pango_line, &ink_rect, &logical_rect); line_link->logical_rect = logical_rect; if (para->formfeed && i == (para_num_lines - 1)) line_link->formfeed = 1; line_link->ink_rect = ink_rect; line_list = g_list_prepend(line_list, line_link); if (logical_rect.height > max_height) max_height = logical_rect.height; } par_list = par_list->next; } /* * not fixed for cairo backend: disable * if (page_layout->do_stretch_chars && page_layout->lpi > 0.0L) page_layout->scale_y = 1.0 / page_layout->lpi * 72.0 * PANGO_SCALE / max_height; */ return g_list_reverse(line_list); } /* * Define PostScript document header information. */ void postscript_dsc_comments(cairo_surface_t *surface, PageLayout *pl) { char buf[CAIRO_COMMENT_MAX]; int x, y; /* * Title */ snprintf(buf, CAIRO_COMMENT_MAX, "%%%%Title: %s", pl->title.c_str()); cairo_ps_surface_dsc_comment (surface, buf); /* * Orientation */ if (pl->do_landscape) { cairo_ps_surface_dsc_comment (surface, "%%Orientation: Landscape"); x = (int)pl->page_height; y = (int)pl->page_width; } else { cairo_ps_surface_dsc_comment (surface, "%%Orientation: Portrait"); x = (int)pl->page_width; y = (int)pl->page_height; } /* * Redefine BoundingBox to cover the whole paper. Cairo creates the entry * based on the text only. This may affect further processing, such as with * convert(1). */ snprintf(buf, CAIRO_COMMENT_MAX, "%%%%BoundingBox: 0 0 %d %d", x, y); cairo_ps_surface_dsc_comment (surface, buf); /* * Duplex */ if (pl->do_duplex) { cairo_ps_surface_dsc_comment(surface, "%%Requirements: duplex"); cairo_ps_surface_dsc_begin_setup(surface); if (pl->do_tumble) cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *Duplex DuplexTumble"); else cairo_ps_surface_dsc_comment(surface, "%%IncludeFeature: *Duplex DuplexNoTumble"); } else cairo_ps_surface_dsc_begin_setup(surface); if (pl->paper_type == PAPER_TYPE_US_LEGAL) cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize Legal"); if (pl->paper_type == PAPER_TYPE_US_LETTER) cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize Letter"); if (pl->paper_type == PAPER_TYPE_A4) cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A4"); if (pl->paper_type == PAPER_TYPE_A3) cairo_ps_surface_dsc_comment (surface, "%%IncludeFeature: *PageSize A3"); } int output_pages(cairo_surface_t *surface, cairo_t *cr, GList *pango_lines, PageLayout *page_layout, PangoContext *pango_context) { int pango_column_height = page_layout->column_height * PANGO_SCALE; int height = 0; int num_pages = -1; // This will be calculated in the measurement pass below int title_height = 0; GList *pango_lines_start = pango_lines; dict_t document_info; // Fill in the static document info build_document_info(page_layout, document_info); document_info["num_pages"] = 0; // Do twice, the first time only measure without shipping for (int i=0; i<2; i++) { int page_idx = 1; bool measure_only = i==0; LineLink *prev_line_link = nullptr; int column_idx = 0; int column_y_pos = 0; column_y_pos = 0; document_info["page_idx"] = page_idx; pango_lines = pango_lines_start; start_page(surface, cr, page_layout, measure_only); if (page_layout->do_draw_header) { title_height = draw_page_header_line_to_page(cr, false, page_layout, pango_context, page_idx, num_pages, document_info, measure_only); column_y_pos = title_height; } if (page_layout->do_draw_footer) draw_page_header_line_to_page(cr, true, page_layout, pango_context, page_idx, num_pages, document_info, measure_only); while(pango_lines) { LineLink *line_link = (LineLink*)pango_lines->data; PangoLayoutLine *line = line_link->pango_line; bool draw_wrap_character = page_layout->do_show_wrap && line_link->wrapped; /* Check if we need to move to next column */ if ((column_y_pos + line_link->logical_rect.height >= pango_column_height) || (prev_line_link && prev_line_link->formfeed)) { column_idx++; column_y_pos = title_height; if (column_idx == page_layout->num_columns) { column_idx = 0; if (!measure_only) eject_page(cr); page_idx++; document_info["page_idx"] = page_idx; start_page(surface, cr, page_layout, measure_only); if (page_layout->do_draw_header) { title_height = draw_page_header_line_to_page(cr, false, page_layout, pango_context, page_idx, num_pages, document_info, measure_only); column_y_pos = title_height; } if (page_layout->do_draw_footer) draw_page_header_line_to_page(cr, true, page_layout, pango_context, page_idx, num_pages, document_info, measure_only); } else { eject_column(cr, title_height/PANGO_SCALE, page_layout, column_idx, measure_only ); } } if (page_layout->lpi > 0.0L) height = (int)(1.0 / page_layout->lpi * 72.0 * PANGO_SCALE); else height = line_link->logical_rect.height; if (!measure_only) draw_line_to_page(cr, column_idx, column_y_pos+height, page_layout, line, draw_wrap_character); column_y_pos += height; pango_lines = pango_lines->next; prev_line_link = line_link; } if (!measure_only) eject_page(cr); if (measure_only) { num_pages = page_idx; document_info["num_pages"] = num_pages; } } return num_pages; } void eject_column(cairo_t *cr, double title_height, PageLayout *page_layout, int column_idx, bool measure_only) { double x_pos, y_top, y_bot, total_gutter; #if 0 fprintf(stderr, "do_draw_separation_line column_idx = %d %d\n", page_layout->do_draw_separation_line, column_idx); #endif if (!page_layout->do_draw_separation_line) return; if (page_layout->pango_dir == PANGO_DIRECTION_RTL) column_idx = (page_layout->num_columns - column_idx); if (column_idx == 1) total_gutter = 1.0 * page_layout->gutter_width /2; else total_gutter = (column_idx - 0.5) * page_layout->gutter_width; x_pos = page_layout->left_margin + page_layout->column_width * column_idx + total_gutter; y_top = page_layout->top_margin + page_layout->header_height + page_layout->header_sep / 2 + title_height; y_bot = page_layout->page_height - page_layout->bottom_margin - page_layout->footer_height; if (!measure_only) { cairo_move_to(cr,x_pos, y_top); cairo_line_to(cr,x_pos, y_bot); cairo_set_line_width(cr, 0.1); cairo_stroke(cr); } } void eject_page(cairo_t *cr) { cairo_show_page(cr); } void start_page(cairo_surface_t *surface, cairo_t *cr, PageLayout *page_layout, bool measure_only) { cairo_identity_matrix(cr); if (output_format == FORMAT_POSTSCRIPT) { char buf[CAIRO_COMMENT_MAX]; int x, y; if (page_layout->do_landscape) { x = (int)page_layout->page_height; y = (int)page_layout->page_width; } else { x = (int)page_layout->page_width; y = (int)page_layout->page_height; } if (!measure_only) { cairo_ps_surface_dsc_begin_page_setup (surface); snprintf(buf, CAIRO_COMMENT_MAX, "%%%%PageBoundingBox: 0 0 %d %d", x, y); cairo_ps_surface_dsc_comment (surface, buf); } } if (page_layout->do_landscape) { if (output_format == FORMAT_POSTSCRIPT) { if (!measure_only) cairo_ps_surface_dsc_comment (surface, "%%PageOrientation: Landscape"); cairo_translate(cr, 0, page_layout->page_width); cairo_rotate(cr, -G_PI_2); } } else { if (output_format == FORMAT_POSTSCRIPT) cairo_ps_surface_dsc_comment (surface, "%%PageOrientation: Portrait"); } } void draw_line_to_page(cairo_t *cr, int column_idx, int column_pos, PageLayout *page_layout, PangoLayoutLine *line, bool draw_wrap_character) { /* Assume square aspect ratio for now */ double y_pos = page_layout->top_margin + page_layout->header_sep + column_pos / PANGO_SCALE; double x_pos = page_layout->left_margin + column_idx * (page_layout->column_width + page_layout->gutter_width); PangoRectangle ink_rect, logical_rect; /* Do RTL column layout for RTL direction */ if (page_layout->pango_dir == PANGO_DIRECTION_RTL) { x_pos = page_layout->left_margin + (page_layout->num_columns-1-column_idx) * (page_layout->column_width + page_layout->gutter_width); } pango_layout_line_get_extents(line, &ink_rect, &logical_rect); if (page_layout->pango_dir == PANGO_DIRECTION_RTL) { x_pos += page_layout->column_width - logical_rect.width / PANGO_SCALE; } cairo_move_to(cr, x_pos, y_pos); pango_cairo_show_layout_line(cr, line); if (draw_wrap_character) { cairo_set_font_face(cr, paps_glyph_face); cairo_set_font_size(cr, glyph_font_size); if (page_layout->pango_dir == PANGO_DIRECTION_LTR) { cairo_move_to(cr, x_pos + page_layout->column_width, y_pos); cairo_show_text(cr, "R"); } else { double left_margin = page_layout->left_margin + (page_layout->num_columns-1-column_idx) * (page_layout->column_width + page_layout->gutter_width); cairo_move_to(cr, left_margin, y_pos); cairo_show_text(cr, "L"); } } } /* * Provide date string from current locale converted to UTF-8. */ string get_date() { time_t t = time(nullptr); GIConv cvh = nullptr; GString *inbuf; char *ib, *ob, obuffer[BUFSIZE * 6], *bp; gsize iblen, oblen; static char *date_utf8 = nullptr; if (date_utf8 == nullptr) { char date[256]; t = time(nullptr); strftime(date, sizeof(date), "%c", localtime(&t)); cvh = g_iconv_open("UTF-8", get_encoding()); if (cvh == (GIConv)-1) { fprintf(stderr, _("%s: Invalid encoding: %s\n"), g_get_prgname(), get_encoding()); exit(1); } inbuf = g_string_new(nullptr); ib = bp = date; iblen = strlen(ib); ob = bp = obuffer; oblen = BUFSIZE * 6 - 1; if (g_iconv(cvh, &ib, &iblen, &ob, &oblen) == (gsize)-1) { fprintf(stderr, _("%1$s: Error while converting date string from '%2$s' to UTF-8.\n"), g_get_prgname(), get_encoding()); /* Return the unconverted string. */ g_string_free(inbuf, false); g_iconv_close(cvh); return date; } obuffer[BUFSIZE * 6 - 1 - oblen] = 0; g_string_append(inbuf, bp); date_utf8 = inbuf->str; g_string_free(inbuf, false); g_iconv_close(cvh); } return date_utf8; } int draw_page_header_line_to_page(cairo_t *cr, bool is_footer, PageLayout *page_layout, PangoContext *ctx, int page, int num_pages, dict_t& document_info, bool measure_only) { PangoLayout *layout = pango_layout_new(ctx); PangoLayoutLine *line; PangoRectangle ink_rect={0,0,0,0}, logical_rect = {0,0,0,0}; /* Assume square aspect ratio for now */ double x_pos, y_pos; int height; gdouble line_pos; /* Reset gravity?? */ // Three lines: // 1. Date // 2. Filename (title) // 3. Page string header = format("{}\n" "{}\n" "{}", page_layout->header_font_desc, get_date().c_str(), page_layout->header_font_desc, page_layout->title.c_str(), page_layout->header_font_desc, page ); vector header_parts = {"","",""}; if (is_footer) { if (page_layout->footer_left) header_parts[0] = page_layout->footer_left; if (page_layout->footer_center) header_parts[1] = page_layout->footer_center; if (page_layout->footer_right) header_parts[2] = page_layout->footer_right; } else { if (page_layout->header_left) header_parts[0]=page_layout->header_left; else header_parts[0]=get_date(); if (page_layout->header_center) header_parts[1] = page_layout->header_center; else header_parts[1] = page_layout->filename; if (page_layout->header_right) header_parts[2] = page_layout->header_right; else header_parts[2] = format("{}",page); } for (auto& v : header_parts) v = format_from_dict(v, document_info); header = ""; for (auto& hp : header_parts) header += format("{}\n", page_layout->header_font_desc, hp); pango_layout_set_markup(layout, header.c_str(), -1); /* The title is in the center */ line = pango_layout_get_line(layout, 0); pango_layout_line_get_extents(line, &ink_rect, &logical_rect); x_pos = page_layout->left_margin; height = logical_rect.height / PANGO_SCALE /3.0; /* The header is placed right after the margin */ if (is_footer) { y_pos = page_layout->page_height - page_layout->bottom_margin*0.5; page_layout->footer_height = height; } else { y_pos = page_layout->top_margin + height; page_layout->header_height = height; } cairo_move_to(cr, x_pos,y_pos); if (!measure_only) pango_cairo_show_layout_line(cr,line); /* output a right edge of header/footer */ line = pango_layout_get_line(layout, 1); pango_layout_line_get_extents(line, &ink_rect, &logical_rect); /* pagenum_rect = logical_rect; */ x_pos = page_layout->left_margin + (page_layout->page_width-page_layout->left_margin-page_layout->right_margin)*0.5 - 0.5*logical_rect.width/PANGO_SCALE; cairo_move_to(cr, x_pos,y_pos); if (!measure_only) pango_cairo_show_layout_line(cr,line); /* output a "center" of header/footer */ line = pango_layout_get_line(layout, 2); pango_layout_line_get_extents(line, &ink_rect, &logical_rect); x_pos = page_layout->page_width - page_layout->right_margin - (logical_rect.width / PANGO_SCALE ); // x_pos = page_layout->page_width - page_layout->right_margin - // ((logical_rect.width + pagenum_rect.width) / PANGO_SCALE + page_layout->gutter_width); cairo_move_to(cr, x_pos,y_pos); if(!measure_only) pango_cairo_show_layout_line(cr,line); g_object_unref(layout); /* header separator */ if (!measure_only && page_layout->do_draw_separation_line) { if (is_footer) line_pos = page_layout->page_height - page_layout->bottom_margin * 1.1; else line_pos = page_layout->top_margin + page_layout->header_height + page_layout->header_sep; line_pos += logical_rect.height/2.0/PANGO_SCALE; cairo_move_to(cr, page_layout->left_margin, line_pos); cairo_line_to(cr,page_layout->page_width - page_layout->right_margin, line_pos); cairo_set_line_width(cr,0.1); // TBD cairo_stroke(cr); } return logical_rect.height; } // Build the document info hash table that may be used in the headers // and footers static void build_document_info(PageLayout* page_layout, dict_t& document_info) { document_info["filename"] = page_layout->filename; document_info["path"] = page_layout->filename_path; GStatBuf stat_buf; g_stat(page_layout->filename_path.c_str(), &stat_buf); document_info["mtime"] = (time_t)stat_buf.st_mtime; document_info["now"] = time(nullptr); page_layout->document_info["num_pages"] = page_layout->num_pages; } string fn_basename(const string& filename) { return basename((char*)filename.c_str()); } dov-paps-f4052ca/subprojects/000077500000000000000000000000001437111362100162135ustar00rootroot00000000000000dov-paps-f4052ca/subprojects/fmt.wrap000066400000000000000000000006761437111362100177050ustar00rootroot00000000000000[wrap-file] directory = fmt-9.1.0 source_url = https://github.com/fmtlib/fmt/archive/9.1.0.tar.gz source_filename = fmt-9.1.0.tar.gz source_hash = 5dea48d1fcddc3ec571ce2058e13910a0d4a6bab4cc09a809d8b1dd1c88ae6f2 patch_filename = fmt_9.1.0-1_patch.zip patch_url = https://wrapdb.mesonbuild.com/v2/fmt_9.1.0-1/get_patch patch_hash = 4557b9ba87b3eb63694ed9b21d1a2117d4a97ca56b91085b10288e9a5294adf8 wrapdb_version = 9.1.0-1 [provide] fmt = fmt_dep